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
更多关于Golang中处理map时遇到的错误问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你是指这里吗?
}
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 的赋值操作。

