在空映射中分配条目

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

assignment to entry in nil map

问题

我正在尝试为在init函数中初始化的map分配值。

但是发生了panic:
assignment to entry in nil map

package main

type Object interface {	
}

type ObjectImpl struct {
}

type Test struct{
    collection map[uint64] Object
}

func (test Test) init(){
    test.collection = make(map[uint64] Object)
}

func main() {
    test :=	&Test{}
    test.init()
    test.collection[1]=&ObjectImpl{}
}

链接:https://play.golang.org/p/yOwXzDkWIo

英文:

I am trying to assign values to a map that is initialized in the init func.

But panic occurs:
assignment to entry in nil map

package main

type Object interface {	
}

type ObjectImpl struct {
}

type Test struct{
    collection map[uint64] Object
}

func (test Test) init(){
    test.collection = make(map[uint64] Object)
}

func main() {
    test :=	&Test{}
    test.init()
    test.collection[1]=&ObjectImpl{}
}

https://play.golang.org/p/yOwXzDkWIo

答案1

得分: 3

该函数以Test作为值传递,因此它会得到它自己的副本。当函数返回时,对test Test所做的所有更改都将消失。改为通过指针传递Test

func (test *Test) init(){
    test.collection = make(map[uint64] Object)
}

需要注意的是,结构体Test是公开的,但方法init不是,因此您的库的用户可能会创建一个Test但没有正确初始化它。Go社区似乎已经建立了一个独立的NewType方法的约定:

type test struct{
    collection map[uint64] Object
}

func NewTest() *test {
    return &test{
        collection: make(map[uint64] Object),
    }
}

这样确保用户只能通过调用NewTest来获取一个test,并且它将按预期进行初始化。

英文:

The function takes Test as value, so it gets its own copy of it. All changes to test Test will be gone when the function returns. Take Test by pointer instead:

func (test *Test) init(){
    test.collection = make(map[uint64] Object)
}

Note though, the struct Test is exported, the method init is not, therefore a user of your library could potentially create a Test but not init it properly. It seems like the go community has established the convention of a freestanding NewType method:

type test struct{
    collection map[uint64] Object
}

function NewTest() *test {
    return &test{
        collection: make(map[uint64] Object),
    }
}

This ensures a user can only obtain a test by calling NewTest and it will be initialized as intended.

答案2

得分: 1

你应该为init方法使用指针接收器:

func (test *Test) init() {  // 使用指向test的指针
    test.collection = make(map[uint64]Object)
}

如果没有使用指针,你将为test对象的副本初始化一个映射。实际的test对象永远不会得到一个初始化的映射。

工作代码

英文:

You should use a pointer receiver for the init method:

func (test *Test) init() {  // use a pointer to test
	test.collection = make(map[uint64] Object)
}

Without a pointer, you are initializing a map for a copy of the test object. The actual test object never gets an initialized map.

Working Code

huangapple
  • 本文由 发表于 2016年8月21日 20:34:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/39064239.html
匿名

发表评论

匿名网友

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

确定