| > One when it's an aliased type that satisfies an interface (again with the nil interfaces!) It sounds like you're again confusing nil interfaces with an interface holding a nil value (in particular, there is no way to get a nil interface from a nil slice). Here's an example that demonstrates nil slices do not cause problems: https://play.golang.org/p/tSA_otqg3- > Another is that it leads to inconsistencies: json.Marshal(([]string)nil) returns "null", for example, not "[]". 1. This is unrelated to the language; it's the behavior implemented by the JSON library 2. This behavior is correct; a nil slice is not the same as an empty slice: fmt.Println([]int(nil) == nil) // true
fmt.Println([]int{} == nil) // false
3. This behavior is consistent: https://play.golang.org/p/NjdO0boHln> As for Option: Not sure how that's an argument. You posited that Go's nils are bad because you can satisfy an error interface with a pointer type, and then when you return (*ConcreteType)(nil), your error handling code executes. The problem here is unrelated to nil or to interfaces; the problem is that you're nesting one binary type inside another (binary in the literal sense of having two states, either nil or not nil in this case). You would have the same problem in Rust had you done Result<Foo, Option<ConcreteError>> or (in the case of a single return value) Option<Option<ConcreteError>>. You would fix the problem in either languages by recognizing that you only have 2 states (error or not error) and removing the nesting (in Rust: Result<Foo, Error> or Option<Error>; in Go `return ConcreteType{}`). > And anyway, a language with real sum types will never allow going down a branch that doesn't receive a correctly matched value. I agree, and it would be nice if Go had this, but this is also not a very significant problem--this problem is blown way out of proportion. |