任务是合并两个相同类型的结构,使得第二个结构中的字段覆盖第一个结构中的字段,但仅如果它们已设置。该解决方案应考虑零值的可能性。
最初的方法考虑使用反射:
func merge(default *Config, file *Config) (*Config) { b := reflect.ValueOf(default).Elem() o := reflect.ValueOf(file).Elem() for i := 0; i < b.NumField(); i++ { defaultField := b.Field(i) fileField := o.Field(i) if defaultField.Interface() != reflect.Zero(fileField.Type()).Interface() { defaultField.Set(reflect.ValueOf(fileField.Interface())) } } return default }
但是,这种方法面临一些问题关于反射的使用以及在所有情况下检查零值的困难。
另一种解决方案利用encoding/json包:
conf := new(Config) // New config *conf = *defConfig // Initialize with defaults err := json.NewDecoder(strings.NewReader(fileContent)).Decode(&conf) if err != nil { panic(err) }
这种方法有几个优点:
在给定的默认配置和文件内容中使用此方法会产生以下输出:
&{S1: S2:file-s2 S3: S4:def S5:file-s5}
这表明:
以上是如何有效地合并两个相同的 Go 结构,并优先考虑第二个结构中的非零值?的详细内容。更多信息请关注PHP中文网其他相关文章!