Make Maps and Slices in Golang - A Guide to Initialization
There are quite a few ways to create new maps and slices in Go, for example, they can both be initialized using the make() function, the new() function, as literals, or by using the var keyword. With so many choices, which option is best? Or perhaps better asked, which one is best in your situation? Let’s take a look.
Slices
var varStyle []string
literalStyle := []string{}
newStyle := new([]string)
makeStyle := make([]string, 0)
var varStyle []string is the idiomatic way to declare an empty slice. The slice is actually nil, which means it will be null when marshalled to JSON and will succeed nil checks.
literalStyle := []string{} should probably only be used when the literal is going to start with values in it, as in literalStyle := []string{"cat", "dog", etc}. Otherwise prefer make()
newStyle := new([]string) returns a pointer to the slice. Same as ptrStyle := &[]string{}. Only use if you want a pointer.
makeStyle := make([]string, 0) is the same as the literal style, but is preferred for idiomatic reasons when the slice doesn’t need non-zero starting values. Make() allows the slice to be initialized with a starting length and capacity, which can have good performance implications in some circumstances:
makeStyle := make([]string, len, cap)
Maps
var varStyle map[int]int
literalStyle = map[string]int{}
newStyle := new(map[string]int)
makeStyle := make(map[string]int)
var varStyle map[int]int creates a nil map. Writing (but not reading interestingly enough) will cause a panic. You probably don’t want a nil map.
literalStyle := map[string]int{} using the literal syntax is just fine, though idiomatically it’s probably best to use a make function. Developers are more used to seeing a make function and make offer some additional features.
newStyle := new(map[string]int) creates a pointer to a nil map… very often not what you want.
makeStyle := make(map[string]int) This is probably what you want! If you know your space requirements you can optimize for allocation by passing in a size:
// Give me a map with room for 10 items before needing to allocate more space
makeStyle := make(map[string]int, 10)
Check out our How To: Global Constant Maps and Slices article if you want to learn more about the proper use of maps and slices in Go.
Related Articles
Go-CoNLLU - Some Much Needed Machine Learning Support in Go
Jun 08, 2020 by Lane Wagner - Boot.dev co-founder and backend engineer
Python is commonly seen as the AI/ML language, but is often a dull blade due to unsafe typing and being slow, like really slow. Many popular natural language processing toolkits only have Python APIs, and we want to see that change. At Nuvi, a social media marketing tool, we use Go for the majority of our data processing tasks because we can write simple and fast code. Today we are open-sourcing a tool that has helped make our ML lives easier in Go. Say hello to go-conllu.
Go's WaitGroup vs JavaScript's PromiseAll
Jun 04, 2020 by Lane Wagner - Boot.dev co-founder and backend engineer
In applications that are i/o heavy, it can get clunky to synchronously execute high-latency functions one after the other. For example, if I have a web page that needs to request seven files from the server before it can show the page, I need to asynchronously fetch all those files at the same time. The alternative of making each request one at a time will take much too long. This is where JavaScript’s PromiseAll and Go’s WaitGroup come in.
How to Sort a Slice in Go
May 27, 2020 by Lane Wagner - Boot.dev co-founder and backend engineer
Sorting is a common task in programming, and for that reason, most languages have a default sorting algorithm in their standard library. Go is one such language. Go has gone about providing sorting functionality in one of the most elegant ways possible, via an interface.
Don't Go To Casting Hell - Use Default Native Types in Go
May 21, 2020 by Lane Wagner - Boot.dev co-founder and backend engineer
Go is strongly typed, and with that, we get many options for simple variable types like integers and floats. The problem arises when we have a uint16, and the function we are trying to pass it into takes an int. We find code riddled with int(myUint16) that can become slow and annoying to read. In other words, when Go developers stray from the “default” type for any given type family, the code can get messy quickly.