猿问

Go中切片的通用类型

我不想拥有多个 API 获取函数,而是想创建一个函数来获取适当的数据库,将其格式化为一个结构切片,然后返回它。以下是我的代码的简化版本:


type Person struct {

        Name   string `json:"name"`

        IsCool bool   `json:"is_cool"`

}


type Pet struct {

        Name     string `json:"name"`

        IsFluffy bool   `json:"is_fluffy"`

}


type Group struct {

        Name         string    `json:"name"`

        CreationDate time.Time `json:"creation_date"`

}


type generic interface{}


func FetchDB(dbName string) interface {

        var collection []generic

        var model      generic


        switch dbName {

        case "users":

                collection = new([]User)

                model      = new(User)

        }

        case "pets":

                collection = new([]Pet)

                model      = new(Pet)

        case "groups":

                collection = new([]Group)

                model      = new(Group)

        default:

                return nil

        }


        iter := client.DB(dbName).Get()


        for {

                entry, err := iter.Next()

                if err != nil {

                        break

                }

                entry.ToStruct(&model)


                collection = append(collection, model)

        }


        return collection

}

但是,调用此函数会导致cannot use new([]User) (type *[]User) as type []generic in assignment. 我的第一个问题是如何创建“通用”切片并为其分配类型。我的第二个问题是,这是否是设置这个功能的正确方法——使用generic界面感觉很hacky!——如果不是,那么设计这个功能的更明智的方法是什么。


慕尼黑5688855
浏览 204回答 1
1回答

炎炎设计

您正在使用new,而不是make切片。这两个是不同的。new为类型分配内存(在这种情况下,是切片,而不是切片的内容),而make创建该类型的实例(make([]User,0) 将创建用户切片)。您可以按如下方式进行这项工作:collection:=make([]generic,0)switch dbName {   case "users":       model      = new(User)   case "pets":       model      = new(Pet)   case "groups":       model      = new(Group)   default:       return nil}而且您model已经是一个指针,并且您希望将数据存储在该指针指向的位置:  entry.ToStruct(model)  // Not &model您正在返回一个interface{},而不是您可以 return []generic,这使您免于使用一种类型断言来获取值的数组部分。但这就是你的问题开始的时候,因为 Go 中没有泛型,你必须编写许多类型断言来获取你需要的数据。有几种方法可以做到这一点。一种方法是收集数据的回调函数:func FetchDB(dbName string, collector func(entry Entry) {  iter := client.DB(dbName).Get()  for {        entry, err := iter.Next()        collector(entry)   }}并将其称为:users:=make([]User,0)FetchDB("users",func(entry Entry) {   var u User   entry.ToStruct(&u)   users=append(users,u)  })
随时随地看视频慕课网APP

相关分类

Go
我要回答