Go 如何填充作为函数引用传递的接口片段

Go 如何填充作为函数引用传递的接口片段,go,struct,types,slice,Go,Struct,Types,Slice,我有一个小例子,我尝试在函数中填充[]条目的(其中条目的是接口)片段,当参数是单个条目时,这很好,但是当尝试传递条目的片段时,我无法找到通过指针的方法 package temp import ( "encoding/json" uuid "github.com/satori/go.uuid" ) type BaseEntry struct { ID uuid.UUID } func (entry *BaseEntry) GetID() uuid.UUID {

我有一个小例子,我尝试在函数中填充[]条目的(其中条目的是接口)片段,当参数是单个条目时,这很好,但是当尝试传递条目的片段时,我无法找到通过指针的方法

package temp

import (
    "encoding/json"

    uuid "github.com/satori/go.uuid"
)

type BaseEntry struct {
    ID uuid.UUID
}

func (entry *BaseEntry) GetID() uuid.UUID {
    return entry.ID
}

type Entry interface {
    GetID() uuid.UUID
}

func GetByCollection(collectionName string, entries []Entry) {
    // This could be a lookup in a database or filesystem

    collections := map[string][]string{
        "books": []string{
            `{"ID": "c8cc718d-94a9-4605-a4bb-05d5aa067fd6", "Title": "Nils Holgersson", "Author": "d89e4a0a-6a65-4754-9090-f8b6c7d6eeec"}`,
            `{"ID": "46ad379e-17f2-4961-b615-d4301160f892", "Title": "Ronja rövardotter", "Author": "a1bba636-0700-474f-8fe8-2ad3ec9d061c"}`,
        },
        "authors": []string{
            `{"ID": "d89e4a0a-6a65-4754-9090-f8b6c7d6eeec", "Name": "Selma Lagerlöf"}`,
            `{"ID": "a1bba636-0700-474f-8fe8-2ad3ec9d061c", "Name": "Astrid Lindgren"}`,
        },
    }

    if collections[collectionName] != nil {
        for _, entryData := range collections[collectionName] {
            entry := BaseEntry{}
            json.Unmarshal([]byte(entryData), &entry)
            *entries = append(*entries, &entry)
        }
    }
}
以及我尝试使用的测试:

    package temp_test

    import (
        "testing"

        "github.com/mojlighetsministeriet/next/temp"
        uuid "github.com/satori/go.uuid"
        "github.com/stretchr/testify/assert"
    )

    type Book struct {
        temp.BaseEntry
    }

    func TestPopulate(test *testing.T) {
        books := []Book{}
        temp.GetByCollection("books", &books)
        assert.NotEqual(test, uuid.Nil, books[0].GetID())
    }
根据我是声明
GetByCollection(collectionName字符串,entries[]Entry)
还是
GetByCollection(collectionName字符串,entries*[]Entry)

# github.com/mojlighetsministeriet/next/temp
./main.go:39:4: invalid indirect of entries (type []Entry)

我应该如何编写,以便可以通过调用GetByCollection来选择条目类型,比如说使用[]Book或[]Author片段填充


我可能需要以某种方式进行重构,最终我喜欢类似于GORM的查询方法()
db.Find(&users)
,但是像
GetByCollection(“books”,和books)
反射需要处理不同的切片类型。以下是如何做到这一点:

func GetByCollection(collectionName string, result interface{}) {    
    collections := map[string][]string{
        "books": []string{
            `{"ID": "c8cc718d-94a9-4605-a4bb-05d5aa067fd6", "Title": "Nils Holgersson", "Author": "d89e4a0a-6a65-4754-9090-f8b6c7d6eeec"}`,
            `{"ID": "46ad379e-17f2-4961-b615-d4301160f892", "Title": "Ronja rövardotter", "Author": "a1bba636-0700-474f-8fe8-2ad3ec9d061c"}`,
        },
        "authors": []string{
            `{"ID": "d89e4a0a-6a65-4754-9090-f8b6c7d6eeec", "Name": "Selma Lagerlöf"}`,
            `{"ID": "a1bba636-0700-474f-8fe8-2ad3ec9d061c", "Name": "Astrid Lindgren"}`,
        },
    }

    slice := reflect.ValueOf(result).Elem()
    elementType := slice.Type().Elem()

    for _, entryData := range collections[collectionName] {
        v := reflect.New(elementType)
        json.Unmarshal([]byte(entryData), v.Interface())
        slice.Set(reflect.Append(slice, v.Elem()))
    }
}
可以这样称呼:

var books []Book
GetByCollection("books", &books)

使用不同的切片类型需要反射。以下是如何做到这一点:

func GetByCollection(collectionName string, result interface{}) {    
    collections := map[string][]string{
        "books": []string{
            `{"ID": "c8cc718d-94a9-4605-a4bb-05d5aa067fd6", "Title": "Nils Holgersson", "Author": "d89e4a0a-6a65-4754-9090-f8b6c7d6eeec"}`,
            `{"ID": "46ad379e-17f2-4961-b615-d4301160f892", "Title": "Ronja rövardotter", "Author": "a1bba636-0700-474f-8fe8-2ad3ec9d061c"}`,
        },
        "authors": []string{
            `{"ID": "d89e4a0a-6a65-4754-9090-f8b6c7d6eeec", "Name": "Selma Lagerlöf"}`,
            `{"ID": "a1bba636-0700-474f-8fe8-2ad3ec9d061c", "Name": "Astrid Lindgren"}`,
        },
    }

    slice := reflect.ValueOf(result).Elem()
    elementType := slice.Type().Elem()

    for _, entryData := range collections[collectionName] {
        v := reflect.New(elementType)
        json.Unmarshal([]byte(entryData), v.Interface())
        slice.Set(reflect.Append(slice, v.Elem()))
    }
}
可以这样称呼:

var books []Book
GetByCollection("books", &books)

您应该使用
entries*[]Entry
作为函数的参数。但请注意,在Go中,
[]Book
不可分配/转换到
[]Entry
,即使
Book
实现了
Entry
,您也必须循环
[]Book
来创建
[]Entry
切片。。。。看这里,我不认为这是测试你的功能的好方法,为什么你不实现你的接口并把它传递给你的测试呢?!感谢@mkopriva提供的链接,似乎我可以从中得到一些东西,感谢您对输入界面->书籍转换解释的澄清。不知何故,当我发送一本&Book并将其作为一个条目并执行json.Unmarshal(dataString,Book)时,这就起到了作用。但是当我发送*[]条目或[]条目时,我无法附加到切片。我可以看看它是否可以返回一个新的片段。谢谢@Danichetta,我试图实现的是有一种方法,可以让您读取/查询/删除JSON文件(在示例中,我将代码简化为一些字符串),作为一个小型数据库实验,因此,除了需要实现Entry之外,我无法预先知道需要支持哪些结构。关于如何测试函数,您还有其他建议吗?您应该使用
entries*[]Entry
作为函数的参数。但请注意,在Go中,
[]Book
不可分配/转换到
[]Entry
,即使
Book
实现了
Entry
,您也必须循环
[]Book
来创建
[]Entry
切片。。。。看这里,我不认为这是测试你的功能的好方法,为什么你不实现你的接口并把它传递给你的测试呢?!感谢@mkopriva提供的链接,似乎我可以从中得到一些东西,感谢您对输入界面->书籍转换解释的澄清。不知何故,当我发送一本&Book并将其作为一个条目并执行json.Unmarshal(dataString,Book)时,这就起到了作用。但是当我发送*[]条目或[]条目时,我无法附加到切片。我可以看看它是否可以返回一个新的片段。谢谢@Danichetta,我试图实现的是有一种方法,可以让您读取/查询/删除JSON文件(在示例中,我将代码简化为一些字符串),作为一个小型数据库实验,因此,除了需要实现Entry之外,我无法预先知道需要支持哪些结构。关于如何测试我的功能,你还有其他建议吗?这看起来很不错,我现在正在尝试。谢谢你,这正是我想要的!很好用!:这看起来真的很好,我现在正在尝试谢谢你这正是我想要的!很好用!:D