我尝试为某个字段分配值,但我的程序会因runtime error: invalid memory address or nil pointer dereference
而感到恐慌。
package main
type Node struct {
Value int
}
func (n *Node) SetValue(value int) {
n.Value = value
}
func main() {
var n *Node
n.SetValue(1)
}
这是合理的,因为变量是零
但我允许一些Go内部结构被允许这样做,例如bytes.Buffer
package main
import "bytes"
import "io"
import "os"
func main() {
var b bytes.Buffer
b.Write([]byte("Hello world"))
io.Copy(os.Stdout, &b)
}
这是`bytes.Buffer源代码
func (b *Buffer) Write(p []byte) (n int, err error) {
b.lastRead = opInvalid
m := b.grow(len(p))
return copy(b.buf[m:], p), nil
}
只有内置结构可以做到的事情,或者我的代码可以实现这一点吗?
修改
这是工作示例。谢谢@twotwotwo的建议。
package main
import "fmt"
type Node struct {
Value int
}
func (n *Node) SetValue(value int) {
n.Value = value
}
func main() {
var n Node
n.SetValue(1)
fmt.Println(n.Value)
}
答案 0 :(得分:6)
关键是var b bytes.Buffer
没有为您提供nil
指针,它会为您提供一个bytes.Buffer
对象,其所有字段的初始值均为零值(以机器术语表示) ,零字节)。 The spec says零值是"假的是布尔值,0是整数,0.0是浮点数,""对于字符串,nil用于指针,函数,接口,切片,通道和映射&#34 ;;请点击该链接了解更多详情。
可以创建自己的零值和the Go team encourages it的结构。 struct Position { x, y int }
是一个简单的例子,Effective Go提供了一个更现实的例子。但请注意,这并不能使 nil指针工作;您仍然需要new(Node)
或var n Node
来分配零Node
。 bytes.Buffer
也是如此。
零值的另一个常见用途:无论用户何时直接创建您的类型的结构(例如,http.Server
),零值是他们不指定的任何字段的默认值。它是许多其他地方的默认设置:如果您从封闭频道收到,可能会获得未找到地图密钥的内容,以及其他可能的地址密钥。