为啥 Go 中的字符串不能为 nil?

Posted

技术标签:

【中文标题】为啥 Go 中的字符串不能为 nil?【英文标题】:Why can't a string be nil in Go?为什么 Go 中的字符串不能为 nil? 【发布时间】:2016-06-30 07:32:21 【问题描述】:

程序available on The Go Playground读取

package main

import "fmt"

func main() 
    var name string = nil
    fmt.Println(name)

并产生错误

prog.go:6: cannot use nil as type string in assignment

我了解"" is the "zero value" for strings。我不明白为什么我不能将nil 分配给我的string

【问题讨论】:

您也不能将nil 分配给ints。为什么这会让你对字符串感到惊讶? 通过防止将 nil 分配给字符串,该语言消除了一类错误。注意string pointers 可以赋值为 nil。 不知道为什么这被否决了。对我来说似乎是一个非常合理的问题 【参考方案1】:

简单的答案是nil 没有定义为language specification 中string 类型的有效值。

...但也许您想要更长的答案?

nil 是指针、接口、通道、切片、映射和函数类型的零值,它表示 未初始化 状态。

考虑以下变量声明:

var a *SomeType
var b interface
var c func()

所有这些变量都有一个代表未初始化状态的值似乎很自然。 a 已被声明为指针,但是当我们还没有将它指向任何东西时,它会指向什么?对于这些类型,nil 显然是零值。

对于通道、切片和映射,它们的零值是nil,原因很简单,因为它们的实现必须在使用前显式初始化。这主要是出于性能原因,这些类型在内部都表示为或多或少复杂的数据结构,并且初始化它们不是免费的。

但是,string 不需要初始化,而且新字符串变量的默认零值是空字符串"" 似乎很自然。因此,nil 没有理由成为有效的字符串值,将其添加到规范只会使语言更复杂,使用起来也更麻烦。

此外,nil 类型的string 代表什么?一个空字符串?我们已经有了。未初始化的字符串?没有这种东西。

【讨论】:

提示:如果处理可选参数 - 但是,您可以将指针传递给您的字符串,并且指针可以为 nil :)(您也可以使用空字符串。) 字符串。”【参考方案2】:

string 是一种数据类型,它不是指向 C/C++ 之类的数组的指针。因此,您不能将其分配给 nil。

【讨论】:

【参考方案3】:

因为 Golang string 是只读的字节切片。

但是,指向字符串 (*string) 的指针可以为 nil:

var s *string
s = nil
readonly := "readonly"
s = &readonly
dereference := *s

https://dhdersch.github.io/golang/2016/01/23/golang-when-to-use-string-pointers.html

【讨论】:

【参考方案4】:

Aedolon 提出了一些好的观点,但更进一步,在其他语言中,字符串是将字节数组表示为字符的便捷方式。我们需要做很多事情,所以这个数组的特定用例获得了很多语言支持,使其更易于使用。但是,问题的核心是使用数组,因为它是一种引用类型,所以它在语言中通常可以为空。也就是说,字符串并不是真正的空值,指向数组的指针是空值。由于许多语言将这两者混为一谈,因此程序员习惯于在使用字符串之前检查字符串是否为空。

Go 不会这样做。字符串不能为 nil,因为 go 中的数据结构不允许它。您可以将指向保存字符表示形式的字节数组的指针设为 null,但这不是字符串。

【讨论】:

以上是关于为啥 Go 中的字符串不能为 nil?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能按照指定的 Go 引用将字符串附加到字节切片?

Swift:String 不能为 nil,那为啥 stringByAddingPercentEncodingWithAllowedCharacters 可以为 nil? [复制]

Go 内置类型 函数 接口

为啥 NSFormatter dateFromString 偶尔会返回 nil?

go Map

为啥我在使用该值时得到一个 nil 值,但当我打印它时它显示为 none nil?