英文:
How to assign to a field of nil struct in golang
问题
我正在尝试为一个字段赋值,但是我的程序出现了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)
}
这是合理的,因为变量是nil。但是我发现一些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)
}
英文:
I'm trying to assign a value to a field, but my program panics with 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)
}
This is reasonable since variable is nil.<br/>
But I've fount some Go internal structs are allowed to do this, e.g. 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)
}
Here is the `bytes.Buffer source code
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
}
Is it the thing only builtin structs can do or it's possible to accomplish this in my code?
EDIT<br/>
Here is the working example. Thanks @twotwotwo for suggestion.
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)
}
答案1
得分: 7
关键的是var b bytes.Buffer
不会得到一个nil
指针,而是得到一个bytes.Buffer
对象,其中所有字段都被初始化为它们的零值(在机器术语中,即零字节)。规范说明零值为“布尔值为false,整数为0,浮点数为0.0,字符串为空字符串,指针、函数、接口、切片、通道和映射为nil”;请点击链接获取更多详细信息。
你可以创建自己的结构体,使其零值起作用,Go团队鼓励这样做。struct Position { x, y int }
是一个简单的例子,Effective Go提供了一个更实际的例子。但请注意,这并不意味着nil指针可以工作;你仍然需要使用new(Node)
或var n Node
来分配零值的Node
。对于bytes.Buffer
也是一样。
零值的另一个常见用途是:无论何时用户直接创建您的类型的结构体(就像人们使用http.Server
一样),零值都是他们未指定字段的默认值。在许多其他地方也是默认值:当你在映射中找不到键时,从关闭的通道接收数据时,以及可能还有其他情况。
英文:
The crucial thing is var b bytes.Buffer
doesn't get you a nil
pointer, it gets you a bytes.Buffer
object with all its fields initialized with their zero values (in machine terms, with zero bytes). The spec says the zero value is "false for booleans, 0 for integers, 0.0 for floats, "" for strings, and nil for pointers, functions, interfaces, slices, channels, and maps"; follow that link for more detail.
It is possible to make your own structs whose zero values work and the Go team encourages it. struct Position { x, y int }
is an easy example and Effective Go gives a more realistic one. But note that that doesn't make the nil pointer work; you would still need new(Node)
or var n Node
to allocate the zero Node
. Same for bytes.Buffer
.
Another common use of zero values: wherever your users create structs of your type directly (as folks do with, say, http.Server
), the zero value is the default for any fields they don't specify. It's the default in a lot of other places: what you get for a not-found map key, if you receive from a closed channel, and probably others.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论