Go为什么键入nil?

时间:2013-11-04 03:53:11

标签: types go null

为什么Go 键入 nil?为方便起见,它会抛出一个显式的接口验证检查。无类型nil的问题是什么?设计师想要用键入的nil解决什么问题?

4 个答案:

答案 0 :(得分:14)

听起来你在问这个错误信息:

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

答案 1 :(得分:12)

这是由于类型安全。 nil实际上是Go中未初始化变量的值。切片,贴图,函数,通道,指针和接口的nil值不是同一类型,并且不具有可比性。有关详细信息,请参阅The language spec

编辑:正如@newacct指出的那样,对此类型的正确技术术语是"zero value"

  
    

当分配内存来存储值时,无论是通过声明还是调用make或new,并且没有提供显式初始化,内存都会被赋予默认初始化。这种值的每个元素都设置为其类型的零值:布尔值为false,整数为0,浮点数为0.0,字符串为“”,指针,函数,接口,切片,通道和映射为nil。 / p>   

Playground example

Why is my nil error value not equal to nil?中的Go FAQ还有一些关于nil接口和错误的信息。

答案 2 :(得分:1)

Golang中的所有变量都需要一个类型。使用:=运算符从右侧表达式的类型推断出类型。

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拒绝这需要明确的类型规范。

答案 3 :(得分:0)

没有typed-nil,就不能使用带有:=值的简短赋值语句nil

a := nil // Error: use of untyped nil
b := error(nil) // OK

同样,它启用以下单行代码:

result, err := "A good result", error(nil)

有时候写上面的东西可能会带来一些方便。


但是请注意,nil不是关键字也不是字面量-Go的 not 没有内置的或标准的 typed-nil 值。 Typed-nil仅由于以下之一而存在:

  • 声明具有默认值(“零值”)的可初始化类型变量
  • nil(直接或间接)分配给键入的值
  • nil标识符转换为一种类型(如上面的示例所示)。

以下是有关带有类型化nil和接口的微妙内容的剪辑:GopherCon 2015: Kevin Cantwell - What Could Go Wrong?