Home > Enterprise >  How to put various structs in a list and manipulate?
How to put various structs in a list and manipulate?

Time:11-27

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)
}

CodePudding user response:

Declare a common interface for the types:

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

Run this playground on the program.

CodePudding user response:

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)

https://go.dev/play/p/InVlnv37yqW

  •  Tags:  
  • go
  • Related