doumi9618 2016-10-01 00:32
浏览 80
已采纳

如何在切片中存储不同结构或在Go中存储结构(不嵌入)

I am new to Golang, after I took a tour of A Tour of Go, I'm trying to make my own thing.

What I want

I want to put different types of the structs into a single slice (or struct?),

so I can use a for loop to pass each struct to a function.

For example

In PHP I can store my classes in an array and pass each of them to foobar() like this:

$classes = [$A, $B, $C, $D];  // $A, $B, $C, $D are classes (called `struct` in Golang).

foreach ($classes as $class)
    foobar($class);

What I tried

I tried to do the same in Golang, and I hope it looks like this:

A{B{}, C{}, D{}}

Since I failed on using slice, I decided to use struct to hold my structs:

type A struct {
    B
    C
    D
}

type B struct {
    Date string
}

type C struct {
    Date string
}

type D struct {
    Date string
}

func main() {   
    // Using reflect to loop the A struct: 
    // http://stackoverflow.com/questions/18926303/iterate-through-a-struct-in-go
    v := reflect.ValueOf(A{})

    for i := 0; i < v.NumField(); i++ {
        foobar(v.Field(i).Interface()) // Passing each struct to the `foobar()` function
    }
}

But it seems like I'm actually doing embedding instead of storing them, any suggestions please?

  • 写回答

1条回答 默认 最新

  • dongzaizai2015 2016-10-01 01:16
    关注

    I think interface{} is what you're after. For example like this:

    type A struct {
        data string
    }
    
    type B struct {
         data int
    }
    
    func printData(s interface{}) {
         switch s.(type) {
             case A:
                 fmt.Printf("A: %s
    ", s.(A).data)
             case B:
                 fmt.Printf("B: %d
    ", s.(B).data)
         }
     }
    
     func main() {
         classes := []interface{}{A{data: "first"}, B{data: 2}, A{data: "third"}}
         for _, c := range classes {
             printData(c)
         }
     }
    

    This is probably as close as you can get to "duck typing" in go.

    Though if your structs are really that similar, you might better off defining a common interface instead and implementing that interface for each struct. Here is same example using interfaces:

    type DataGetter interface {
        getDate() string
    }
    
    type A struct {
        data string
    }
    
    func (a A) getDate() string {
        return a.data
    }
    
    type B struct {
        data int
    }
    
    func (b B) getDate() string {
        return fmt.Sprintf("%d", b.data)
    }
    
    func printData(s DataGetter) {
        fmt.Printf("%s
    ", s.getDate())
    }
    
    func main() {
    
        classes := []DataGetter{A{data: "first"}, B{data: 2}, A{data: "third"}}
        for _, c := range classes {
            printData(c)
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥60 用visual studio编写程序,利用间接平差求解水准网
  • ¥15 Llama如何调用shell或者Python
  • ¥20 谁能帮我挨个解读这个php语言编的代码什么意思?
  • ¥15 win10权限管理,限制普通用户使用删除功能
  • ¥15 minnio内存占用过大,内存没被回收(Windows环境)
  • ¥65 抖音咸鱼付款链接转码支付宝
  • ¥15 ubuntu22.04上安装ursim-3.15.8.106339遇到的问题
  • ¥15 blast算法(相关搜索:数据库)
  • ¥15 请问有人会紧聚焦相关的matlab知识嘛?
  • ¥15 网络通信安全解决方案