为什么Go语言使用类型化的
nil
?它可以为了方便而触发显式接口确认检查。未经类型化的nil
有何问题?设计者们打算用类型化的nil
解决什么问题?听起来你在询问这个错误信息:
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()
}
这将打印:
prog.go:17: use of untyped nil
[process exited with non-zero status]
在这个例子中,程序应该打印"A"还是"B"?
你需要帮助编译器做出决定。你可以通过指定n
的类型来实现。
例如:
http://play.golang.org/p/zMxUFYgxpy
func main() {
var n *A
n.Foo()
}
打印“ A”。
在其他语言中,如果n为nil或其等效物,则n.Foo()
可能会立即崩溃。 Go的语言设计者决定让您确定应该发生什么。如果在未检查nil
的情况下访问指针,则会获得与其他语言相同的行为。
nil
调用类型化方法既有意义又有用。 - Dustinvar SomeNil := SomeType(nil)
。如果我稍后使用“SomeNil”与一个函数进行比较(这里的SomeType是一个函数),它不起作用,声称“func只能与nil进行比较”。 - Eric Burelnil
实际上是未初始化变量的值。对于切片、映射、函数、通道、指针和接口的 nil
值不同且不可比较。有关详细信息,请参见语言规范。Playground 示例 还有一些关于 nil 接口和错误的信息,可以在Go FAQ中的“为什么我的 nil 错误值不等于 nil?”中找到。当为值分配内存时,通过声明或调用 make 或 new,但没有提供显式初始化,则该内存会得到默认初始化。此类值的每个元素都设置为其类型的零值:布尔值为 false,整数为 0,浮点数为 0.0,字符串为空串,指针、函数、接口、切片、通道和映射为 nil。
Go中的所有变量都需要指定类型。使用:=
操作符可以从右侧表达式的类型推断出变量的类型。
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
对于几乎所有的表达式来说,由于需要在某个地方明确指定类型,或者在未指定时具有默认值,因此它们的类型是明确无误的。唯一的例外是nil
。
n := nil // var n ???
nil
是以下类型的有效值:
当用户键入nil
时,没有一个好的默认类型,因此Golang拒绝此操作,需要明确指定类型。
:=
来表示nil
值。a := nil // Error: use of untyped nil
b := error(nil) // OK
result, err := "A good result", error(nil)
在某些情况下,编写类似上面的内容可能会提供一些方便。
请注意,nil
不是关键字或字面量 - Go 没有内置或标准的类型化 nil 值。 只有在以下情况下才存在类型化 nil:
nil
(直接或间接地)赋给一个类型化的值nil
标识符强制转换为类型(如上例所示)。这里有一个关于类型化 nil 和接口的微妙之处的剪辑:GopherCon 2015: Kevin Cantwell - What Could Go Wrong?
Optional<T>
那样显式地类型化nil,可能会更好。 - eonilnil
。nil
本身没有类型。然而,nil
可以从所处的上下文中获得类型,以便进行直接的比较,例如。 - undefined