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.