Go中切片的常规键入

问题描述 投票:-2回答:1

而不是具有多个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界面感觉很糟糕!),如果不是,那么设计此功能的更明智的方法是什么。

go
1个回答
0
投票

您正在使用new,而不是make用于切片。那两个是不同的。 new为该类型分配内存(在这种情况下,为切片,而不是切片的内容),而make为该类型创建实例(make([] User,0)将为Users的切片) 。

您可以按照以下步骤进行这项工作:

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{},而您可以返回[]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) 
 })
© www.soinside.com 2019 - 2024. All rights reserved.