Golang中解决复杂结构体赋值nil map时的Panic错误

Golang中解决复杂结构体赋值nil map时的Panic错误 完整代码:https://play.golang.org/p/bctvsy7ARqS

package main

import (
	"fmt"
)

type Plan struct {
	BufferMeasures map[string]*ItemSiteMeasure
}
type ItemSiteMeasure struct {
	itemtest string
}

func main() {

	fmt.Println("start")
	var buff Plan
	buff.AddBuffer()
	fmt.Println("end")

}

func (p *Plan) AddBuffer() {
	fmt.Println("method start")
	p.BufferMeasures["itmsit1"] = &ItemSiteMeasure{itemtest: "item1"}
	fmt.Println("obj values : ", p.BufferMeasures)
	fmt.Println("method end")
}

错误/输出:

start method start panic: assignment to entry in nil map

goroutine 1 [running]: main.(*Plan).AddBuffer(0xc000068f50) /tmp/sandbox633108119/prog.go:29 +0xe8 main.main() /tmp/sandbox633108119/prog.go:20 +0x90


更多关于Golang中解决复杂结构体赋值nil map时的Panic错误的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

petrus:

if p.BufferMeasures == nil { p.BufferMeasures = make(map[string]*ItemSiteMeasure) }

谢谢 Petrus,问题已解决。

更多关于Golang中解决复杂结构体赋值nil map时的Panic错误的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


要初始化一个映射,请使用内置的 make 函数

Go 博客:Go 映射实战


package main

import (
	"fmt"
)

type Plan struct {
	BufferMeasures map[string]*ItemSiteMeasure
}
type ItemSiteMeasure struct {
	itemtest string
}

func main() {
	fmt.Println("start")
	var buff Plan
	buff.AddBuffer()
	fmt.Println("end")
}

func (p *Plan) AddBuffer() {
	if p.BufferMeasures == nil {
		p.BufferMeasures = make(map[string]*ItemSiteMeasure)
	}
	fmt.Println("method start")
	p.BufferMeasures["itmsit1"] = &ItemSiteMeasure{itemtest: "item1"}
	fmt.Println("obj values : ", p.BufferMeasures)
	fmt.Println("method end")
}

. start method start obj values : map[itmsit1:0xc000010230] method end end

在Golang中,当尝试向nil map赋值时会引发panic。在你的代码中,Plan结构体的BufferMeasures字段是nil map,需要先初始化才能使用。

以下是修正后的代码:

package main

import (
	"fmt"
)

type Plan struct {
	BufferMeasures map[string]*ItemSiteMeasure
}

type ItemSiteMeasure struct {
	itemtest string
}

func main() {
	fmt.Println("start")
	var buff Plan
	buff.AddBuffer()
	fmt.Println("end")
}

func (p *Plan) AddBuffer() {
	fmt.Println("method start")
	
	// 初始化map
	if p.BufferMeasures == nil {
		p.BufferMeasures = make(map[string]*ItemSiteMeasure)
	}
	
	p.BufferMeasures["itmsit1"] = &ItemSiteMeasure{itemtest: "item1"}
	fmt.Println("obj values : ", p.BufferMeasures)
	fmt.Println("method end")
}

或者,你可以在创建Plan实例时直接初始化map:

func main() {
	fmt.Println("start")
	
	// 方法1:使用make初始化
	buff := Plan{
		BufferMeasures: make(map[string]*ItemSiteMeasure),
	}
	
	// 方法2:先声明后初始化
	var buff2 Plan
	buff2.BufferMeasures = make(map[string]*ItemSiteMeasure)
	
	buff.AddBuffer()
	fmt.Println("end")
}

还可以在结构体方法中提供更安全的初始化方式:

func (p *Plan) initBufferMeasures() {
	if p.BufferMeasures == nil {
		p.BufferMeasures = make(map[string]*ItemSiteMeasure)
	}
}

func (p *Plan) AddBuffer() {
	fmt.Println("method start")
	p.initBufferMeasures()
	p.BufferMeasures["itmsit1"] = &ItemSiteMeasure{itemtest: "item1"}
	fmt.Println("obj values : ", p.BufferMeasures)
	fmt.Println("method end")
}

关键点是:在Golang中,map是引用类型,声明后默认值为nil,必须使用make()函数或字面量初始化后才能进行赋值操作。

回到顶部