0

我想知道如何将以下功能简化为一个功能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)
}
4

3 回答 3

5

这样做的 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

于 2016-08-11T00:03:32.377 回答
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
于 2016-08-11T07:48:24.457 回答
0

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

通过制作一个可嵌入的结构,并让每个具有类似功能的结构嵌入它,您可以减少代码的行数,尽管“简化”可能有点牵强。

type HasIDs struct {
   Ids []string
}

type AA struct {   
   HasIDs
   OtherValues []int
}

type BB struct {
   HasIDs
   OtherValues []byte
}

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

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

并在将结构与方法一起嵌入的任一结构上调用该方法。

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

这是一个工作代码示例: https: //play.golang.org/p/ys_CN_L_cr

于 2016-08-11T00:03:04.210 回答