Go语言中如何将多种struct存入列表并操作同名同类型字段
实现方案
方案1:公共接口实现(推荐)
Go 语言中不同类型结构体要存入同一个切片,最符合语言设计习惯的做法是定义公共接口,约束你需要的字段操作逻辑,各个结构体分别实现该接口即可,该方案类型安全、无额外运行时开销。
package main import "fmt" // 定义公共接口,约束Cnt字段的操作 type CntOperator interface { IncrementCnt() GetCnt() int } type A struct { Cnt int } // A实现接口方法 func (a *A) IncrementCnt() { a.Cnt++ } func (a *A) GetCnt() int { return a.Cnt } type B struct { Cnt int } // B实现接口方法 func (b *B) IncrementCnt() { b.Cnt++ } func (b *B) GetCnt() int { return b.Cnt } func main() { a := &A{} b := &B{} // 切片类型声明为接口类型即可存入所有实现了该接口的结构体实例 list := []CntOperator{ a, b, } for _, item := range list { item.IncrementCnt() } fmt.Printf("a.Cnt: %d, b.Cnt: %d", a.GetCnt(), b.GetCnt()) }
运行后输出结果为:a.Cnt: 1, b.Cnt: 1,符合预期。
方案2:反射实现
如果涉及的结构体数量较多,不想逐个实现接口方法,可以使用空接口切片存储任意类型结构体,再通过反射统一操作同名字段,该方案灵活性更高,但存在一定运行时开销,且字段名、类型错误只能在运行时发现,需要自行添加校验逻辑避免panic。
package main import ( "fmt" "reflect" ) type A struct { Cnt int } type B struct { Cnt int } func main() { a := &A{} b := &B{} // 空接口切片可以存储任意类型的实例 list := []any{ a, b, } for _, item := range list { // 通过反射获取指针对应的结构体元素 v := reflect.ValueOf(item).Elem() // 取Cnt字段 cntField := v.FieldByName("Cnt") // 校验字段有效性和类型后再操作 if cntField.IsValid() && cntField.Kind() == reflect.Int { cntField.SetInt(cntField.Int() + 1) } } fmt.Printf("a.Cnt: %d, b.Cnt: %d", a.Cnt, b.Cnt) }
内容的提问来源于stack exchange,提问作者Takuya HARA
相关产品推荐
相关产品推荐

