Golang 嵌套struct如何通过字段名实现间接赋值?
Go 结构体动态按字段名赋值实现方案
Go 是静态强类型语言,本身不原生支持 [] 下标语法直接访问结构体字段,你要的动态赋值效果可以通过以下三种方案实现:
方案1:switch 封装方法(最推荐,性能最优)
你的场景字段数量少且固定,直接为结构体封装取值方法即可,没有额外运行时开销,代码示例:import "fmt" type Categories struct { A ABCDE `json:"A"` B ABCDE `json:"B"` C ABCDE `json:"C"` D ABCDE `json:"D"` E ABCDE `json:"E"` } type ABCDE struct { Foo string `json:"foo"` } // GetABCDE 通过字段名获取对应ABCDE字段的指针 func (c *Categories) GetABCDE(field string) (*ABCDE, error) { switch field { case "A": return &c.A, nil case "B": return &c.B, nil case "C": return &c.C, nil case "D": return &c.D, nil case "E": return &c.E, nil default: return nil, fmt.Errorf("非法字段名: %s", field) } }使用方式:
categories := Categories{} item, err := categories.GetABCDE("A") if err != nil { // 处理字段不存在的异常 } item.Foo = "Salute"方案2:reflect 反射实现(通用性强)
如果结构体字段多、后续会频繁调整,可以用反射实现通用的动态赋值逻辑,不需要每次新增字段都改方法:import ( "fmt" "reflect" ) func SetCategoryFoo(c *Categories, fieldName string, fooVal string) error { // 必须传入结构体指针才能修改字段值 catVal := reflect.ValueOf(c).Elem() // 按名称查找字段 targetField := catVal.FieldByName(fieldName) if !targetField.IsValid() || targetField.Type() != reflect.TypeOf(ABCDE{}) { return fmt.Errorf("字段%s不存在或类型不匹配", fieldName) } // 获取Foo字段的反射对象 fooField := targetField.FieldByName("Foo") if !fooField.CanSet() { return fmt.Errorf("字段Foo不允许修改") } // 赋值 fooField.SetString(fooVal) return nil }使用方式:
categories := Categories{} err := SetCategoryFoo(&categories, "A", "Salute") if err != nil { // 处理异常 }方案3:直接用map替代结构体(写法最简单)
如果你不需要结构体的编译期类型校验,可以直接把Categories定义为map类型,完全符合你写的伪代码语法:type Categories map[string]ABCDE使用方式:
// 初始化 categories := Categories{} // 直接按下标赋值,完全符合你的需求写法 categories["A"] = ABCDE{Foo: "Salute"} // 也可以修改已存在的字段 categories["A"].Foo = "New Value"该方案的缺点是字段名没有编译期校验,写错字段名只会在运行时报错。
内容的提问来源于stack exchange,提问作者Markus Bach
相关产品推荐
相关产品推荐

