Golang多态参数和返回

时间:2014-02-07 20:06:01

标签: go

说我有功能:

func ToModelList(cats *[]*Cat) *[]*CatModel {
    list := *cats
    newModelList := []*CatModel{}
    for i := range list {
        obj := obj[i]
        newModelList = append(newModelList, obj.ToModel())
    }
    return &newModelList
}

func ToModelList(dogs *[]*Dog) *[]*DogModel {
    list := *dogs
    newModelList := []*DogModel{}
    for i := range list {
        obj := obj[i]
        newModelList = append(newModelList, obj.ToModel())
    }
    return &newModelList
}

有没有办法将这两者结合起来,所以我可以做一些像

这样的事情
func ToModelList(objs *[]*interface{}) *[]*interface{} {
    list := *objs
    // figure out what type struct type objs/list are
    newModelList := []*interface{}
    // type cast newModelList to the correct array struct type
    for i := range list {
        obj := obj[i]
        // type cast obj based on objs's type
        newModelList = append(newModelList, obj.ToModel())
    }
    return &newModelList
}

3 个答案:

答案 0 :(得分:3)

首先,切片已经是一个引用,除非您需要更改切片本身,否则不需要将其作为指针传递。 其次,接口{}可以是对象或指向对象的指针。您不需要* interface {}。

我不确定你想要实现的目标,但你可以这样做:

package main

// Interface for Cat, Dog
type Object interface {
        ToModel() Model
}

// Interface for CatModel, DogModel
type Model interface {
        Name() string
}

type Cat struct {
        name string
}

func (c *Cat) ToModel() Model {
        return &CatModel{
                cat: c,
        }
}

type CatModel struct {
        cat *Cat
}

func (c *CatModel) Name() string {
        return c.cat.name
}

type Dog struct {
        name string
}

func (d *Dog) ToModel() Model {
        return &DogModel{
                dog: d,
        }
}

type DogModel struct {
        dog *Dog
}

func (d *DogModel) Name() string {
        return d.dog.name
}

func ToModelList(objs []Object) []Model {
        newModelList := []Model{}
        for _, obj := range objs {
                newModelList = append(newModelList, obj.ToModel())
        }
        return newModelList
}

func main() {
        cats := []Object{
                &Cat{name: "felix"},
                &Cat{name: "leo"},
                &Dog{name: "octave"},
        }
        modelList := ToModelList(cats)

        for _, model := range modelList {
                println(model.Name())
        }
}

您可以为您的Cat,Dogs等以及您的模型定义接口。然后你可以根据需要实现它们,并且很容易做到ToModelList()。

答案 1 :(得分:1)

你可以让* CatModel和* DogModel都实现类型PetModel {}接口,只需在函数签名中返回[] Pet。

func (cats []*Cat) []PetModel {
    ...
    return []*CatModel {...}
}
func (dogs []*Dog) []PetModel {
    ...
   return []*DogModel {...}
}

BTW:在golang中返回一个切片的指针是没用的。

答案 2 :(得分:0)

如果你去除冗余的赋值和不必要的指针切片,你会发现你剩下的代码很少,并且为每个模型类型复制它看起来并不那么糟糕。

func CatsToCatModels(cats []*Cat) []*CatModel {
    var result []*CatModel
    for _, cat := range cats {
        result = append(result, cat.ToModel())
    }
    return result
}

除非在很多地方使用此代码,否则我也会考虑将其内联,因为它是简单的代码,内联时只有4行。

是的,你可以用interface{}替换所有类型并使代码通用,但我不认为这是一个很好的权衡。