因此,正如我在评论中提到的,如果您希望能够从字段中获取单个元素,最简单的方法tableRecord.Data就是将字段类型更改为实际类型:


type tableRecord struct {

    PrimaryKey string

    Data       []interface{} // slice of whatever

}

这样,你可以写一些非常通用的东西:


for tbl, record := range records {

    fmt.Printf("First record from table %s\n", tbl)

    b, _ := json.MarshalIndent(record[0], " ", "  ")

    fmt.Println(string(b))

    fmt.Prinln("other records...")

    b, _ = json.MarshalIndend(record[1:], " ", "  ")

    fmt.Println(string(b))

}

不过,如果我是你,我会考虑在我的数据库类型中实现一个接口。类似的东西:


type DBType interface {

    PrimaryKey() string

    TableName() string // xorm can use this to get the table name

    Slice() []DBType // can return []user or whatever

}

所以你真的不需要tableRecord类型了,可以像这样使用 var:


listOfTables := []DBType{user{}, ...}

for _, tbl := range listOfTables {

    data := tbl.Slice()

    // find data here

    fmt.Printf("First record from table %s\n", tbl.TableName())

    b, _ := json.MarshalIndent(data[0], " ", "  ")

    fmt.Println(string(b))

    fmt.Prinln("other records...")

    b, _ = json.MarshalIndend(data[1:], " ", "  ")

    fmt.Println(string(b))

}

所以 TL;DR 我的回答/评论中缺少的内容:


[]user{}从 type (or []DBTable) to 的转换[]interface{}不起作用,因为您不能在单个表达式中转换切片中的所有元素。您必须创建第二个类型切片[]interface{}并像这样复制值:


slice := userVar.Slice() data := make([]interface{}, len(slice)) for i := range slice { data[i] = slice[i] // 复制类型到 interface{} slice } 返回表记录{userVar.PrimaryKey(), 数据}


我已经创建了一个小的工作示例来说明如何使用上述接口。


演示

为避免太多混乱,您可以更改Slicefunc 以[]interface{}立即返回 a:


func(v T) Slice() []interface{

    return []interface{

        &T{},

    }

}

你的实施有什么问题Slice是你有这样的事情:


func (u *user) Slice() []DBTable {

    u = &user{} // you're re-assigning the receiver, losing all state!

    return []DBTable{u}

}

接收器是指针类型,因此您所做的任何重新分配都会影响调用 func 的变量。那不是一个好主意。只使用值接收器,或者,如果你想确保接口只在指针变量上实现(一个常见的技巧,例如 gRPC 使用的)是像这样实现函数:


func(*user) Slice() []DBTable{

    return []DBTable{&user{}}

}

pb.go这个技巧的一个很好的例子可以在使用协议缓冲区时生成的文件中找到。消息类型将具有如下功能:


func(*MsgType) ProtoMessage() {}