为什么 Go 有type nil
?为方便起见,它会引发显式接口构造检查。untyped 的问题是nil
什么?设计师想用 typed 解决什么问题nil
?
4 回答
听起来您在询问此错误消息:
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.Foo()
如果n
isnil
或其等价物可能会立即崩溃。Go 的语言设计者决定让你决定应该发生什么。如果您在不检查 的情况下访问指针nil
,您将获得与其他语言相同的行为。
这是由于类型安全。nil
实际上是Go中未初始化变量的值。切片、映射、函数、通道、指针和接口的nil
值不是同一类型,不具有可比性。有关详细信息,请参阅语言规范。
编辑:正如@newacct所指出的,正确的技术术语是该类型的“零值”:
当通过声明或调用 make 或 new 分配内存来存储值时,并且未提供显式初始化,则为内存提供默认初始化。这种值的每个元素的类型都设置为零值:布尔值为 false,整数为 0,浮点数为 0.0,字符串为 "",指针、函数、接口、切片、通道和映射为 nil。
在Why is my nil error value not equal to nil?中还有一些关于 nil 接口和错误的信息?在Go 常见问题解答中。
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 拒绝了这需要显式类型规范。
如果没有 typed-nil,您将无法使用:=
带有nil
值的简短赋值语句。
a := nil // Error: use of untyped nil
b := error(nil) // OK
同样,它支持以下单行:
result, err := "A good result", error(nil)
写上面这样的东西有时可能会提供一些便利。
但是请注意,这nil
不是关键字或文字——Go没有内置或标准的 typed-nil值。Typed-nil 仅作为以下之一的结果存在:
- 使用默认(“零值”)初始化声明一个可空类型变量
nil
(直接或间接)分配给类型化的值- 将
nil
标识符转换为类型(如上面的示例所示)。
这是一个关于类型化 nil 和接口的微妙之处的剪辑:GopherCon 2015:Kevin Cantwell - 会出什么问题?