If you’re looking to learn more about arrays in Go, the best place to start is Go Slices: usage and internals on the Go blog. The following merely expands on the article’s points and demonstrates a few gotchas.
For instance, there are multiple ways to initialize both arrays and slices, and it’s not always obvious which one will be created:
Initialization | Type |
---|---|
[3]int{1, 2, 3} |
array |
[...]int{1, 2, 3} |
array |
var a [3]int |
array |
a[:] |
slice |
var s []int |
slice |
[]int{1, 2, 3} |
slice |
make([]int, 3) |
slice |
The zero value of a slice may be nil
, but don’t expect it to have a length:
log.Println(len(nil))
./nil.go:6: use of untyped nil
Unless you specify a type:
var slice []int = nil
log.Println(len(slice))
// 0
You can use nil
as a valid parameter or field value:
type Package struct {
Name string
Dependencies []string
}
func main() {
unsafe := Package{Name: "unsafe", Dependencies: nil}
log.Println(unsafe, len(unsafe.Dependencies))
// {unsafe []} 0
}
Despite a newly created slice being nil
, it is able to undergo append
operations immediately. No call to make
is necessary:
var Primes []int
Primes = append(Primes, 2, 3, 5, 7)
This also works if the slice is the field of a struct
:
type Node struct {
Name string
Children []Node
}
func Nodes() {
A := Node{Name: "A"}
B := Node{Name: "B"}
A.Children = append(A.Children, B)
}
Or a named return value:
func CreateFibonacci() (Fibonacci []int) {
Fibonacci = append(Fibonacci, 1, 1, 2, 3, 5, 8)
return
}
Or my favorite, the value of a map:
regions := make(map[string][]string)
regions["Europe"] = append(regions["Europe"], "France", "Germany")
regions["Africa"] = append(regions["Africa"], "Djibouti", "Egypt")
But watch out, the JSON output of a slice will vary depending on the initialization method:
var a []int
jsonA, _ := json.Marshal(a)
b := make([]int, 0)
jsonB, _ := json.Marshal(b)
log.Printf("jsonA: %s\n", jsonA)
log.Printf("jsonB: %s\n", jsonB)
// jsonA: null
// jsonB: []
Golint will suggest replacing the latter syntax despite the difference in output:
slices.go:12:2: can probably use "var b []int" instead
Slices are unhashable and cannot be used as keys:
xy := make(map[[]int]string)
./xy.go:6: invalid map key type []int
But arrays are hashable:
xy := make(map[[2]int]string)
xy[[2]int{3, 4}] = "Battleship"
log.Println(xy)
// map[[3 4]:Battleship]
They are not, however, valid keys in JSON objects:
output, err := json.Marshal(xy)
if err != nil {
log.Fatal(err)
}
json: unsupported type: map[[2]int]string
Happy Hacking!