为什么在Go语言中字符串不能为nil?

huangapple go评论108阅读模式
英文:

Why can't a string be nil in Go?

问题

这是一个可在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

我理解""是字符串的“零值”。但我不明白为什么我不能将nil赋值给我的string变量。

英文:

The program available on The Go Playground reads

package main

import "fmt"

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

and yields an error

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

I understand "" is the "zero value" for strings. I don't understand why I cannot assign nil to my string.

答案1

得分: 86

简单的答案是,在语言规范中,nil并没有被定义为string类型的有效值。

...但也许你想要一个更详细的答案?

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

考虑以下变量声明:

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

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

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

然而,string类型不需要初始化,对于一个新的字符串变量来说,一个空字符串""作为默认的零值似乎是很自然的。因此,nil没有成为有效的字符串值的理由,将其添加到规范中只会使语言变得更复杂,使用起来更加繁琐。

此外,nil作为string类型的值会代表什么呢?一个空字符串?我们已经有了这个。一个未初始化的字符串?这样的东西是不存在的。

英文:

The simple answer is that nil is not defined to be a valid value for type string in the language specification.

...but maybe you want a longer answer?

nil is the zero value for pointers, interfaces, channels, slices, maps and function types, and it represents an uninitialized state.

Consider the following variable declarations:

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

It seems natural that all these variables would have a value that represents uninitialized state. a has been declared as a pointer, but what would it point to, when we haven't yet pointed it at anything? nil is an obvious zero value for these types.

As for channels, slices and maps, their zero value is nil for the simple reason that their implementation is such that they must be explicitly initialized before they can be used. This is mostly for performance reasons, these types are all represented internally as more or less complex data structures, and initializing them is not free.

However, a string doesn't require initialization, and it seems natural that the default, zero value for a new string variable would be an empty string, "". Therefore there's simply no reason for nil to be a valid string value, and adding it to the specification would only make the language more complicated and much more cumbersome to work with.

Furthermore, what would nil of type string represent? An empty string? We already have that. An uninitialized string? There's no such thing.

答案2

得分: 13

在Go语言中,string是一种数据类型,而不是像C/C++中的指向数组的指针。因此,你不能将其赋值为nil

英文:

In go string is a data type and not a pointer to an array as in C/C++. As such you can't assign it to nil.

答案3

得分: 8

因为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

英文:

Because Golang string is a read-only slices of bytes.

However, a pointer to a string (*string) can be 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

得分: 1

Aedolon提出了一些好观点,但更进一步来说,在其他语言中,字符串是表示字节数组的字符的便捷方式。我们经常需要这样做,所以这种特定的数组用法得到了很多语言支持,以使其更容易使用。然而,实质上,你正在使用一个数组,而数组在某些语言中通常可以为null,因为它是引用类型。也就是说,字符串本身并不是null,指向数组的指针为null。由于许多语言混淆了这两个概念,程序员习惯于在使用字符串之前检查它是否为null。

但Go语言不会这样做。在Go中,字符串不能为nil,因为Go的数据结构不允许。你可以将指向包含字符表示的字节数组的指针设置为null,但那不是一个字符串。

英文:

Aedolon made some good points, but to go further, in other languages strings are convenient ways of representing arrays of bytes as characters. We need to do this a lot, so this specific use case of an array gets a lot of language support to make it easier to use. However, at the heart of the matter, you are working with an array, which is often able to be null in a language because it is a reference type. That is, the string isn't really null, the pointer to the array is null. Because many languages conflate these two things, programmers are used to having to check if a string is null before using it.

Go doesn't do this. A string cannot be nil, because the data structure in go doesn't allow it. You can have a pointer to a byte array holding character representations in go be null, but that isn't a string.

huangapple
  • 本文由 发表于 2016年3月15日 10:10:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/36001477.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定