Golang中处理map时遇到的错误问题

Golang中处理map时遇到的错误问题 错误: panic: 对空映射中的条目进行赋值

goroutine 1 [运行中]: github.com/SpecterTeam/SpecterGO/utils.(*Config).Set(…) /home/fris/go/src/github.com/SpecterTeam/SpecterGO/utils/Config.go:157 退出状态 2

以下是代码:

const (
TypeJson = iota // .json
TypeYaml // .yml & .yaml
)

type(
Content map[string]interface{}

Config struct {
	file       string
	config     Content
	configType int
}
)

func NewConfig(file string, configType int, defaults map[string]interface{}) Config  {
c := Config{}
c.SetConfigType(configType)
c.SetFile(file)
if FileExists(file) {
if ext := filepath.Ext(file); ExtMatchType(ext, configType) {
c.SetConfig(c.Unmarshal())
} else {
err := errors.New("Ext of " + file + " doesn't match the configType!")
HandleError(err)
}
} else {
os.Create(file)
}
for key, value := range defaults {
c.CheckDefault(key, value)
}
c.Save()
return c
}

func (c *Config) CheckDefault(key string, value interface{}) {
if !c.Exist(key) {
c.Set(key, value)
}
}

func ExtMatchType(ext string, configType int) bool {
switch configType {
case TypeJson:
if ext == "json" {
return true
} else {
return false
}
case TypeYaml:
if ext == "yml" || ext == "yaml" {
return true
} else {
return false
}
}
return false
}

func (c *Config) Marshal() ([]byte, error) {
var b []byte

switch c.ConfigType() {
case TypeYaml:
	b,_ = yaml.Marshal(c.Config())
case TypeJson:
	b,_ = json.Marshal(c.Config())
default:
	err := errors.New("couldn't marshal the Config, Perhaps because the type of the config isn't set")
	return b, err
}

return b, nil
}

func (c *Config) Unmarshal() Content {
var r Content
switch c.ConfigType() {
case TypeYaml:
bts,_ := ioutil.ReadFile(c.File())
yaml.Unmarshal(bts,&r)
case TypeJson:
bts,_ := ioutil.ReadFile(c.File())
json.Unmarshal(bts,&r)
}
return r
}

func (c *Config) Save() {
bts, err := c.Marshal()
if err != nil {
HandleError(err)
} else {
ioutil.WriteFile(c.File(), bts, 0644)
}

}

func (c *Config) ConfigType() int {
return c.configType
}

func (c *Config) SetConfigType(configType int) {
c.configType = configType
}

func (c *Config) Config() Content {
return c.config
}

func (c *Config) SetConfig(config Content) {
c.config = config
}

func (c *Config) File() string {
return c.file
}

func (c *Config) SetFile(file string) {
c.file = file
}

func (c *Config) Set(key string, value interface{}) {
c.config[key] = value
}

func (c *Config) Get(key string) *interface{} {
i := c.config[key]
return &i
}

func (c *Config) Remove(key string) {
config := c.Config()
delete(config, key)
}
func (c *Config) Exist(key string) bool {
config := c.Unmarshal()
_,exist := config[key]
return exist
}

更多关于Golang中处理map时遇到的错误问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

考虑以下错误信息

对空映射中的条目进行赋值

并与关于如何使用映射的信息相关联,例如在Go语言之旅中所述。

更多关于Golang中处理map时遇到的错误问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你是指这里吗?

github.com

}
func (c *Config) SetFile(file string) {
	c.file = file
}

func (c *Config) Set(key string, value interface{}) {
	if c.config == nil {
		c.config = make(Content)
	}
	c.config[key] = value
}

func (c *Config) Get(key string) interface{} {
	return c.config[key]
}

func (c *Config) Remove(key string) {
	delete(c.config, key)
}

??

这个错误是因为在 Set 方法中尝试对未初始化的 map 进行赋值导致的。在 Go 中,map 类型的零值是 nil,直接对 nil map 进行赋值会触发 panic。

问题出现在 NewConfig 函数中,当创建新的 Config 实例时,config 字段没有被初始化,仍然是 nil。然后在 CheckDefault 方法中调用 Set 方法时就会触发 panic。

以下是修复方案:

func NewConfig(file string, configType int, defaults map[string]interface{}) Config {
    c := Config{}
    c.SetConfigType(configType)
    c.SetFile(file)
    // 初始化 config map
    c.SetConfig(make(Content))
    
    if FileExists(file) {
        if ext := filepath.Ext(file); ExtMatchType(ext, configType) {
            c.SetConfig(c.Unmarshal())
        } else {
            err := errors.New("Ext of " + file + " doesn't match the configType!")
            HandleError(err)
        }
    } else {
        os.Create(file)
    }
    for key, value := range defaults {
        c.CheckDefault(key, value)
    }
    c.Save()
    return c
}

func (c *Config) SetConfig(config Content) {
    if config == nil {
        c.config = make(Content)
    } else {
        c.config = config
    }
}

另外,Exist 方法也有问题,它每次都重新从文件解析配置,而不是使用内存中的配置:

func (c *Config) Exist(key string) bool {
    _, exist := c.config[key]
    return exist
}

还有一个潜在的问题是 Remove 方法:

func (c *Config) Remove(key string) {
    delete(c.config, key)
}

这样修改后,map 会在创建 Config 实例时正确初始化,避免了对 nil map 的赋值操作。

回到顶部