英文:
Golang: Is there a way to iterate over a slice in a generic way using reflect?
问题
有没有一种使用反射以通用方式迭代切片的方法?
type LotsOfSlices struct {
As []A
Bs []B
Cs []C
//.... 还有很多这样的切片
}
type A struct {
F string
//.... 和其他结构体不同的很多其他属性
}
type B struct {
F string
//.... 和其他结构体不同的很多其他属性
}
type C struct {
F string
//.... 和其他结构体不同的很多其他属性
}
我想使用反射来减少代码复杂性和重复代码。这种做法可行吗?这是一个不好的主意吗?
例如,不是这样写:
func processData(l LotsOfSlice){
for _, a := range l.As{
// 使用 a.F
}
for _, b := range l.Bs{
// 使用 b.F
}
for _, c := range l.Cs{
// 使用 c.F
}
...
}
而是像这样写:
func processData(l LotsOfSlices){
t := reflect.TypeOf(l)
for i := 0; i < t.NumField(); i++ {
zs := reflect.ValueOf(l).Field(i).Interface()
for _, z := range zs{
// 使用 z.F
}
}
}
英文:
Is there a way to iterate over a slice in a generic way using reflection?
type LotsOfSlices struct {
As []A
Bs []B
Cs []C
//.... and lots more of these
}
type A struct {
F string
//.... and lots of other stufff that's different from the other structs
}
type B struct {
F string
//.... and lots of other stufff that's different from the other structs
}
type C struct {
F string
//.... and lots of other stufff that's different from the other structs
}
I want to use reflection to reduce code complexity and duplicate code. Is this possible? Is this a bad idea?
For example, not this:
func processData(l LotsOfSlice){
for _, a := range l.As{
// use a.F
}
for _, b := range l.Bs{
// use b.F
}
for _, c := range l.Cs{
// use c.F
}
...
}
But something like this instead:
func processData(l LotsOfSlices){
t := reflect.TypeOf(l)
for i := 0; i < t.NumField(); i++ {
zs := reflect.ValueOf(l).Field(i).Interface()
for _, z := range zs{
// use z.F
}
}
}
答案1
得分: 2
使用Value.Len和Value.Index来迭代数组或切片:
func processData(l LotsOfSlices) {
v := reflect.ValueOf(l)
for i := 0; i < v.NumField(); i++ {
f := v.Field(i)
if f.Kind() != reflect.Slice {
continue
}
for i := 0; i < f.Len(); i++ {
e := f.Index(i)
s := e.FieldByName("F")
// 对 s 进行操作
}
}
}
请注意,这是一段Go语言代码,用于处理包含多个切片的结构体。在代码中,使用reflect
包中的Value.Len
和Value.Index
函数来获取切片的长度和索引元素。然后,可以使用FieldByName
函数来获取结构体字段的值。你可以在代码中的注释部分添加对s
变量的操作。
英文:
Use Value.Len and Value.Index to iterate over an array or slice:
func processData(l LotsOfSlices) {
v := reflect.ValueOf(l)
for i := 0; i < v.NumField(); i++ {
f := v.Field(i)
if f.Kind() != reflect.Slice {
continue
}
for i := 0; i < f.Len(); i++ {
e := f.Index(i)
s := e.FieldByName("F")
// Do something with s
}
}
}
答案2
得分: 0
如果你的结构体产生类似的结果(返回int或操作字符串),但每个结构体类型的操作方式是独特的,你可以在它们上定义函数:
func (a *A) GetResult() int { // 求两个数的和
return a.p1 + a.p2
}
func (b *B) GetResult() int { // 求两个数的差
return b.p1 - b.p2
}
func (c *C) GetResult() int { // 求两个数的积
return c.p1 * c.p2
}
然后定义一个接口Operable
:
type Operable interface {
GetResult() int // 共享的函数
}
接下来,编写一个函数,该函数接受该接口作为参数,任何实现该接口中所有函数的结构体都可以作为参数传入:
func processOperable(o []Operable) {
for _, v := range o {
v.GetResult() // 对于每个结构体都是独特的操作
}
}
英文:
if your structs do similar end result (returns int or operates on strings) but does so uniquely for each struct type you can define functions on them:
func (a *A) GetResult() int { // sums two numbers
return a.p1 + a.p2
}
func (b *B) GetResult() int { // subtracts two numbers
return b.p1 - b.p2
}
func (c *C) GetResult() int { // times two numbers
return c.p1 * c.p2
}
then define an interface Operable
type Operable interface {
GetResult() int // shared function
}
then make a function that accepts the interface as argument, and any struct that implements all functions in that interface can be accepted into it as an argument
func processOperable(o []Operable){
for _, v := range o{
v.GetResult() --> unique for each struct
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论