在一个结构体中嵌入两个同名的结构体。

13

如何在一个结构体中嵌入两种同名类型的变量?例如:

type datastore {
    *sql.Store
    *file.Store
}

出现duplicate field Store的结果。我知道这是有道理的,因为您将无法引用嵌入字段ds.Store,但您如何完成此操作呢?

澄清一下,我想要使用datastore实现一个接口。为此,需要两个结构体,因为它们的方法互补以创建接口。我有什么其他选择吗?


请问您能否详细说明一下这些嵌入式结构的方法是如何完美地互相补充的呢? - kostix
请查看我的答案,我相信这是解决这个问题更优雅的方式。 - Mostafa Zeinali
4个回答

22
使用 类型别名,例如:
type SqlStore = sql.Store // this is a type alias

type datastore struct {
    *SqlStore
    *file.Store
}

类型别名并不会创建一个与其所创建的类型不同的新类型。它只是引入了一个别名 sqlStore,作为 sql.Store 所表示类型的另一种拼写方式。

5
你可以尝试将你的whatever.Store首先包装到不同命名的类型中:
import (
    "os"
    "whatever/sql"
)

type SqlStore struct {
    *sql.Store
}

type FileStore struct {
     *os.File
}

type DataStore struct {
     SqlStore
     FileStore
}
Playground链接
请注意,Go 1.9可能会支持类型别名:请参见这个这个。我不确定这是否有助于您的情况,但了解一下可能是有趣的。

1

在你的结构体中,你可以简单地给这两个“存储”命名不同的名称。当你在结构体中没有给一个嵌入式结构体字段命名时,默认使用嵌入式结构体的名称作为字段名。所以,在这里,你有两个名为“Store”的字段,但你可以很容易地让它们的名称明确。因此,请使用以下代码:

package main

import (
    "file"
    "fmt"
    "sql"
)

type Datastore struct {
    sqlStore  *sql.Store
    fileStore *file.Store
}

func main() {
    ds := Datastore{&sql.Store{SqlStoreName: "MySQLStore"}, &file.Store{FileStoreName: "MyFileStore"}}

    fmt.Println(ds.sqlStore.SqlStoreName, ds.fileStore.FileStoreName)
}

这对我来说很好用。

1

即使在两个不同的子结构中作为匿名字段包含,您确实可以引用一个字段:

package main

import "fmt"

type A struct {
    x int32
}

type B struct {
    x int32
}

type C struct {
    A
    B
}

func main() {
    c := C{A{1}, B{2}}
    //fmt.Println(c.x) // Error, ambiguous
    fmt.Println(c.A.x) // Ok, 1
    fmt.Println(c.B.x) // Ok, 2
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接