I'm a newbie Go programmer confused by the below behaviour. I expected the program to fail at t2 with error
first argument to append must be a slice; have untyped nil
but Go is happy when passing in nil as first parameter to append when it's a parameter to a method?
package main
import "fmt"
type Thing struct {
data []string
}
func NewThing(extra []string) Thing {
return Thing{
data: append(extra, "b"),
}
}
func main() {
t := NewThing([]string{"a"})
fmt.Println(t.data) // [a b]
t2 := NewThing(nil)
fmt.Println(t2.data) // [b]
//_ = Thing{ // build failed: first argument to append must be a slice; have untyped nil
// data: append(nil, "b"),
//}
}
Playground: https://go.dev/play/p/Cxi7fRHu3Wi
Is this just a convenience feature or am I understanding this wrong?
CodePudding user response:
It is a convenience that the capacity and length of a nil slice is zero. From there, append works as normal when passed a nil slice.
The call append(nil, "b") does not compile because nil has no type. The compiler cannot determine the type of the result because the slice argument does not have a type.
The call append(extra, "b") works when extra is nil because extra is a typed value (a []string). Given the slice type, the compiler knows that the result is []string and that the appended elements must be assignable to string.
The call append([]string(nil), "b") also works because the expression []string(nil) is a typed value.
