golang中的nil表示什么?

97

在golang中,有许多情况需要使用nil。例如:

func (u *URL) Parse(ref string) (*URL, error) {
    refurl, err := Parse(ref)
    if err != nil {
        return nil, err
    }
    return u.ResolveReference(refurl), nil
}

但是我们不能像这样使用它:
var str string //or var str int
str = nil

在进行赋值操作时,如果使用了 nil 作为字符串类型,golang 编译器会报错 can't use nil as type string in assignment

看起来 nil 只能用于结构体和接口的指针。如果是这样的话,那么它是什么意思? 当我们将其与其他对象进行比较时,它们如何比较,换句话说,golang 如何确定一个对象是 nil

编辑:例如,如果接口为 nil,则其类型和值必须同时为 nil。golang 如何实现这一点?


4
你需要理解Go语言类型和每种类型对象可能具有的不同值。所有与nil相关的细节,包括哪些东西可以为nil、可赋值为nil、可与nil比较等等,都在https://golang.org/ref/spec中进行了解释。该文档篇幅短小、易于一次性阅读,并且内容清晰易懂。 - Volker
1
在Go中,空字符串是""。要测试一个字符串是否有值,只需执行str == ""即可。 - libertylocked
1
https://www.youtube.com/watch?v=ynoY2xz-F8s - Maria Ines Parnisari
9个回答

174

在 Go 中,nil 是指针、接口、映射、切片、通道和函数类型的零值,表示一个未初始化的值。

nil 不意味着某种"未定义"的状态,它本身就是一个合法的值。在 Go 中,如果一个对象的值是 nil,那么它就是 nil,只有当它属于前面提到的类型之一时才可能是这样。

error 是一个接口,因此 nil 是其中的一个有效值,而对于 string 来说则不是。显然,nil 错误表示没有错误


请查看此处的规范:https://golang.org/ref/spec#Variables - Janac Meena
我认为围绕这个设计很傻。我正在开发一个需要返回nil并将指针设置为nil的项目。但是当检查是否为nil时,我的测试失败了,因为类型被擦除了。为什么他们不能只把nil或null变为null而不指向任何东西呢? - TheRealChx101

9

nil在 Go 中就是其他语言中的 NULL 指针值。

你可以有效地将它用于任何指针或接口(接口有点像指针)。

你可以将其用作错误,因为错误类型是一个接口

你不能将其用作字符串,因为在 Go 中,字符串是一个值。

nil 在 Go 中是无类型的,这意味着你不能这样使用:

var n = nil

由于这里缺少n的类型,但是你可以这样做:
var n *Foo = nil

请注意,nil是指针和接口的零值,未初始化的指针和接口将为nil

2
错误:nil没有类型。它没有被类型化。你不能这样做:var n = nil,不是因为nil有一个类型,而是因为编译器无法推断出n的类型,它无法推迟类型,因为nil没有类型。 - Inanc Gumus
1
感谢您指出这个错别字,即使是在回答之后这么长时间。进行编辑会更加合适。但还是非常感谢。 - Elwinar
没问题。 - Inanc Gumus
1
附加示例:func getStuff() string { return nil }不会编译,并显示cannot use nil as type string in return argument。在Java中,public String getStuff() { return null; }完全正常工作。不确定您所说的“字符串是一个值”的含义-字符串是一组字节。 - yname
一个 string 是一个值,与指针(或者是一个接口——本质上是一个指针)相对。也许术语“具体类型”更加精确,但我认为对于初学者来说并不更易理解。 - Elwinar

4

nil也是一个值,但唯一的区别是它是空的。

在Javascript中,未初始化的变量将是undefined。同样,Golang对于所有未初始化的数据类型都有nil作为默认值。


2
在Go语言中,“nil”表示指针、接口、映射、切片和通道的零值。它意味着该值未初始化。请注意,保留HTML标签。

1
在Go中,nil是一个预定义的标识符,代表指针、接口、通道、映射、切片和函数类型中的空值。未初始化的指针和接口将是nil。字符串不符合以上类型之一,因此无法被赋值为nil
如果您使用简写声明声明变量,例如:variable:=nil,那么编译器将会报错,因为它不知道应该将variable赋值给哪种类型。
在Go中,映射、切片和函数不支持比较,但可以与nil进行比较。 如果将任意两个映射、切片或函数分配为nil并彼此进行比较,则会引发运行时错误。 但是,如果我们将nil分配给任意两个指针变量并将它们相互比较,则不会发生错误。
package main

import (
"fmt"
)

 func main() {
    var i *int =nil
    var j *int =nil
    if i==j {
      fmt.Println("equal")
    } else {
      fmt.Println("no")
    }
}

这段代码运行良好,并输出equal

1
  • 对于像切片和指针这样“引用”其他类型的数据类型,“nil”表示变量没有引用任何实例(在其他语言中等同于null指针)。
  • 它是函数、映射、接口、通道和结构类型变量的零值。

1

nil 是 Go 语言中的预声明标识符,表示指针、接口、通道、映射、切片和函数类型的零值nil 是指针和接口的零值,未初始化的指针和接口将为 nil

在 Go 中,字符串不能为 nil。字符串不符合赋值为 nil 的条件。

a := nil   // It will throw an error 'use of untyped nil'

var a *int = nil  //It will work

1
你的代码中有错别字吗?请查看 https://play.golang.org/p/G3a2aqgjcnj。 - user12817546

0
在Golang中,可以使用nil作为指针、接口、映射、切片、通道、函数类型和错误的数据类型。
字符串中,值为""。
整数中,值为

在任何其他编程语言中,"" 都是一个有效的字符串。但 Google 对此有些奇怪 :/ - TheRealChx101

0
Golang 中,零值 是已定义变量的默认值。不同数据类型的默认值为:
  • 整型类型为0
  • 浮点型类型为0.0
  • 布尔类型为false
  • 字符串类型为""
  • 接口类型、切片类型、通道类型、映射类型、指针类型和函数类型的默认值为nil
因此,对于接口类型、切片类型、通道类型、映射类型、指针类型和函数类型,nil 是其零值或默认值。
例如,
var a int
var s []int
var s1 []int = []int{1, 2}

fmt.Println(a == nil) // throw error
// invalid operation: a == nil (mismatched types int and untyped nil)

fmt.Println(s == nil) // true
fmt.Println(s1 == nil) // false

由于error是一个接口,我们可以这样编写

_, err := Parse("")
if err != nil { // if there is an error
  // handle error
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接