英文:
How to put various structs in a list and manipulate?
问题
我想以编程的方式操作具有相同名称和类型的各种结构体字段,就像下面的示例一样,但我不知道如何将不同的结构体放入一个列表中。
package main
import "fmt"
type A struct {
Cnt int
}
type B struct {
Cnt int
}
func main() {
a := &A{}
b := &B{}
list := []something{
a,
b,
}
for _, item := range list {
item.Cnt++
}
fmt.Printf("a.Cnt: %d, b.Cnt: %d", a.Cnt, b.Cnt)
}
英文:
I want to manipulate various structs' field which has same name and type programmatically like the following but I have no idea how to put varied structs in a list.
package main
import "fmt"
type A struct {
Cnt int
}
type B struct {
Cnt int
}
func main() {
a := &A{}
b := &B{}
list := []something{
a,
b,
}
for _, item := range list {
item.Cnt++
}
fmt.Printf("a.Cnt: %d, b.Cnt: %d", a.Cnt, b.Cnt)
}
答案1
得分: 3
为类型声明一个通用接口。方法应该反映你想要在值上执行的任何操作。这里我使用add作为增量的概括。
type Cntr interface {
Add(i int)
}
在每个类型上实现该接口:
func (a *A) Add(i int) { a.Cnt += i }
func (b *B) Add(i int) { b.Cnt += i }
声明一个接口类型的切片,并使用类型A和B的值:
a := &A{}
b := &B{}
list := []Cntr{ // <-- 接口类型的切片
a,
b,
}
增加计数器:
for _, item := range list {
item.Add(1)
}
打印结果:
fmt.Printf("a.Cnt: %d, b.Cnt: %d", a.Cnt, b.Cnt)
// 输出 a.Cnt: 1, b.Cnt: 1
英文:
Declare a common interface for the types. The methods should reflect whatever action you want to executed on the values. I use add here as generalization of increment.
type Cntr interface {
Add(i int)
}
Implement that interface on each type:
func (a *A) Add(i int) { a.Cnt += i }
func (b *B) Add(i int) { b.Cnt += i }
Declare slice of interface type and with values of types *A and *B:
a := &A{}
b := &B{}
list := []Cntr{ // <-- slice of the interface type
a,
b,
}
Increment the counters:
for _, item := range list {
item.Add(1)
}
Print the results:
fmt.Printf("a.Cnt: %d, b.Cnt: %d", a.Cnt, b.Cnt)
// prints a.Cnt: 1, b.Cnt: 1
答案2
得分: 1
使用反射API来获取任意结构类型中命名字段的指针:
func getFieldPtr(v interface{}, name string) interface{} {
return reflect.ValueOf(v).Elem().FieldByName(name).Addr().Interface()
}
使用方法如下:
a := &A{}
b := &B{}
list := []interface{}{
a,
b,
}
for _, item := range list {
pcnt := getFieldPtr(item, "Cnt").(*int)
*pcnt++
}
fmt.Printf("a.Cnt: %d, b.Cnt: %d", a.Cnt, b.Cnt)
你可以在这里查看代码示例:https://go.dev/play/p/InVlnv37yqW
英文:
Use the reflect API to get a pointer to a named field in an arbitrary struct type:
func getFieldPtr(v interface{}, name string) interface{} {
return reflect.ValueOf(v).Elem().FieldByName(name).Addr().Interface()
}
Use it like this:
a := &A{}
b := &B{}
list := []interface{}{
a,
b,
}
for _, item := range list {
pcnt := getFieldPtr(item, "Cnt").(*int)
*pcnt++
}
fmt.Printf("a.Cnt: %d, b.Cnt: %d", a.Cnt, b.Cnt)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论