问题
Why does Go have typed nil? It throws an explicit interface conformation check for convenience. What's the problem of untyped nil and what did the designers want to solve with typed nil?
回答1:
It sounds like you're asking about this error message:
http://play.golang.org/p/h80rmDYCTI
package main
import "fmt"
type A struct {}
type B struct {}
func (a *A) Foo() {
fmt.Println("A")
}
func (b *B) Foo() {
fmt.Println("B")
}
func main() {
n := nil
n.Foo()
}
This prints:
prog.go:17: use of untyped nil
[process exited with non-zero status]
In that example, should the program print "A" or "B"?
You have to help the compiler decide. The way you do that is by specifying the type of n.
For example:
http://play.golang.org/p/zMxUFYgxpy
func main() {
var n *A
n.Foo()
}
prints "A".
In other languages, n.Foo() might crash immediately if n is nil or its equivalent. Go's language designers decided to let you determine what should happen instead. If you access the pointer without checking for nil, you get the same behavior as in other languages.
回答2:
This is due to type safety. nil is actually the value of uninitialized variables in Go. The nil values for slices, maps, functions, channels, pointers and interfaces are not the same type, and not comparable. See The language spec for more details.
EDIT: As pointed out by @newacct the correct technical term for this is the "zero value" for the type:
When memory is allocated to store a value, either through a declaration or a call of make or new, and no explicit initialization is provided, the memory is given a default initialization. Each element of such a value is set to the zero value for its type: false for booleans, 0 for integers, 0.0 for floats, "" for strings, and nil for pointers, functions, interfaces, slices, channels, and maps.
Playground example
There is also some information regarding nil interfaces and errors at Why is my nil error value not equal to nil? in the Go FAQ.
回答3:
All variables in Golang need to have a type. Using := operator infers the type from type of right-side expression.
x := [0]int{} // var x [0]int
y := make(chan int) // var y chan int
z := map[int]int{} // var z map[int]int
a := func(int) {} // var a func(int)
b := 42 // var b int
c := 42.0 // var c float64
For pretty much any expression, its type is unambigous, due to needing to explicitly specify the type somewhere - or in case of number literals, having a default when unspecified. The only exception to this rule is nil.
n := nil // var n ???
nil is a valid value for the following.
- Pointers
- Unsafe pointers
- Interfaces
- Channels
- Maps
- Slices
- Functions
There isn't a good default for a type when an user types nil, so instead Golang rejects this requiring an explicit type specification.
回答4:
Without typed-nil, you couldn't use the short assignment statement := with the nil value.
a := nil // Error: use of untyped nil
b := error(nil) // OK
It, likewise, enables the following one-liner:
result, err := "A good result", error(nil)
Writing something like the above may provide some convenience on occasion.
Note, however, that nil is not a keyword or a literal -- and Go does not have a built-in or standard typed-nil value. Typed-nil exists only as the result of one of the following:
- declaring a nillable typed variable with default ("zero value") initialization
- assigning
nil(directly or indirectly) to a typed value - casting the
nilidentifier to a type (as shown in the examples above).
Here's a clip about subtleties with typed nils and interfaces: GopherCon 2015: Kevin Cantwell - What Could Go Wrong?
来源:https://stackoverflow.com/questions/19761393/why-does-go-have-typed-nil