33

为什么 Go 有type nil?为方便起见,它会引发显式接口构造检查。untyped 的问题是nil什么?设计师想用 typed 解决什么问题nil

4

4 回答 4

21

听起来您在询问此错误消息:

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()如果nisnil或其等价物可能会立即崩溃。Go 的语言设计者决定让你决定应该发生什么。如果您在不检查 的情况下访问指针nil,您将获得与其他语言相同的行为。

于 2013-11-04T04:06:18.693 回答
17

这是由于类型安全。nil实际上是Go中未初始化变量的值。切片、映射、函数、通道、指针和接口的nil值不是同一类型,不具有可比性。有关详细信息,请参阅语言规范。

编辑:正如@newacct所指出的,正确的技术术语是该类型的“零值”

当通过声明或调用 make 或 new 分配内存来存储值时,并且未提供显式初始化,则为内存提供默认初始化。这种值的每个元素的类型都设置为零值:布尔值为 false,整数为 0,浮点数为 0.0,字符串为 "",指针、函数、接口、切片、通道和映射为 nil。

游乐场示例

在Why is my nil error value not equal to nil?中还有一些关于 nil 接口和错误的信息?在Go 常见问题解答中。

于 2013-11-04T11:18:03.773 回答
5

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 拒绝了这需要显式类型规范。

于 2018-05-03T19:46:31.607 回答
5

如果没有 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 - 会出什么问题?

于 2019-07-29T18:13:32.750 回答