采用不同类型结构

时间:2016-08-10 23:35:42

标签: go go-reflect

我想知道以下函数lengthAAlengthBB如何简化为一个函数。注意在这两个函数中它只是计算数组的长度,它只是一个例子,可能比这更复杂。理想情况下,我只想要一个用于相同目的的函数(在本例中为len),但可以将不同的struct作为变量。

type A struct {
   id string
}

type AA struct {
   ids []A
}

type B struct {
   id string
   value bool
}

type BB struct {
   ids []B
}

func lengthAA(aa AA) int {
   return len(aa)
}

func lengthBB(bb BB) int {
   return len(bb)
}

3 个答案:

答案 0 :(得分:3)

执行此操作的Go方式是AABB实现常用方法。然后,length将接受包含相同功能签名的接口。例如:

package main

import (
    "fmt"
)

type Lengther interface {
    Length() int
}

type A struct {
    id string
}

type AA struct {
    ids []A
}

func (a *AA) Length() int {
    return len(a.ids)
}

type B struct {
    id    string
    value bool
}

type BB struct {
    ids []B
}

func (b *BB) Length() int {
    return len(b.ids)
}

func length(l Lengther) int {
    return l.Length()
}

func main() {
    aa := &AA{
        ids: make([]A, 10),
    }
    bb := &BB{
        ids: make([]B, 34),
    }
    fmt.Println(length(aa))
    fmt.Println(length(bb))
}

https://play.golang.org/p/DdxP5lFcZi

答案 1 :(得分:1)

1-使用两个独立的接收方法length(),就像这样的工作示例代码(这是惯用的Go):

package main

import "fmt"

func (v *AA) length() int {
    return len(v.ids)
}
func (v *BB) length() int {
    return len(v.ids)
}

func main() {
    aa := AA{[]A{A{"id"}, A{"id2"}}}
    fmt.Println(aa.length()) // 2
    bb := BB{[]B{B{"id", true}, B{"id2", true}}}
    fmt.Println(bb.length()) // 2
}

type A struct {
    id string
}

type AA struct {
    ids []A
}

type B struct {
    id    string
    value bool
}

type BB struct {
    ids []B
}

2-使用一个length(aa interface{})函数,就像这个工作示例代码一样(在某些用例中这很有用):

package main

import "fmt"

func length(aa interface{}) int {
    switch v := aa.(type) {
    case AA:
        return len(v.ids)
    case BB:
        return len(v.ids)
    }
    return -1
}

func main() {
    aa := AA{[]A{A{"id"}, A{"id2"}}}
    fmt.Println(length(aa)) // 2
    bb := BB{[]B{B{"id", true}, B{"id2", true}}}
    fmt.Println(length(bb)) // 2
}

type A struct {
    id string
}

type AA struct {
    ids []A
}

type B struct {
    id    string
    value bool
}

type BB struct {
    ids []B
}

3-使用reflect和一个length(v interface{})函数,就像这个工作示例代码一样(在某些用例中这很有用):

package main

import "fmt"
import "reflect"

func length(v interface{}) int {
    return reflect.ValueOf(v).FieldByName("ids").Len()
}

func main() {
    aa := AA{[]A{A{"id"}, A{"id2"}}}
    fmt.Println(length(aa)) // 2
    bb := BB{[]B{B{"id", true}, B{"id2", true}}}
    fmt.Println(length(bb)) // 2
}

type A struct {
    id string
}

type AA struct {
    ids []A
}

type B struct {
    id    string
    value bool
}

type BB struct {
    ids []B
}

输出:

2
2

答案 2 :(得分:0)

这段代码实际上不会编译,因为len(aa)会将结构传递给len,这会失败。但我认为我得到了你想要做的事情,而最好的方法是使用最接近的东西Go继承,这实际上只是结构嵌入。

通过制作一个可嵌入的结构体,并且让每个具有相似特征的结构嵌入它,你可以减少代码的行数,尽管“简化”可能有点延伸。

type HasIDs struct {
   Ids []string
}

type AA struct {   
   HasIDs
   OtherValues []int
}

type BB struct {
   HasIDs
   OtherValues []byte
}

此时,结构AABB的值均为Ids []string。现在,您可以为HasIDs结构提供一个两个结构都应该能够调用的方法。

func (hasIds HasIDs) length() {
    return len(hasIds.Ids)
}

在任何使用方法嵌入结构的struct上调用该方法。

a1 := AA{}
aLength := a1.length()

以下是一个有效的代码示例:https://play.golang.org/p/ys_CN_L_cr