go - 接口(interface)类型的函数返回(另一个)接口(interface)类型的结构

标签 go struct

我试图在两个存储之间创建一个中间层,它从存储 A 中获取数据,将其转换为相应类型的存储 B,然后存储它。由于我需要转换大约 50-100 种类型,我希望使用 map[string]func 并根据 storageA.Type 确定我需要的转换函数打电话。

这些转换函数中的每一个都将返回不同的结构,它们都反射(reflect)了存储 B 中的不同类型。这些存储 B 结构中的每一个都实现了一个公共(public)接口(interface),因此它们可以调用函数。

归根结底,我的问题是我无法将 func(StorageAType) StorageBType1 转换为 func(StorageAType) StorageBType,即使 StorageBtype1 实现了接口(interface) StorageBType

我创建了这个相当长的 playground因为我意识到用文字描述问题很棘手。注释掉第 38-41 行和 60-63 行将使其运行,但这是我想使用的那些行。对不起,它的大小,但我想不出一个不那么冗长但清晰的例子。

请注意,我必须重新创建我的 stackoverflow 帐户,所以我认为我没有代表可以对答案发表评论。

*编辑:

非常典型。问完才知道怎么解决。通过在转换器函数中返回接口(interface)类型而不是确切类型,在此 playground 中进行了更改.

最佳答案

具有不同结果类型的函数类型是不同的类型,其中一个结果类型是否实现了另一个并不重要。 Spec: Function types:

A function type denotes the set of all functions with the same parameter and result types.

StorageBtype1StorageBType 是不同的类型,因此以它们作为结果类型的函数类型也不同,并且不能使用其中一种函数类型的值作为另一个的值(value)。

只需将所有转换器函数的结果类型更改为StorageBType:

func TypeA3ToTypeB1(i StorageAType) StorageBType {
    return StorageBType1{i.Type}
}

func TypeA5ToTypeB2(i StorageAType) StorageBType {
    return StorageBType2{i.Type, i.Name}
}

由于所有返回值都实现了 StorageBType,因此这是一个有效的更改,不需要对转换器函数的实现进行任何更改。

现在调用这些函数当然会返回一个StorageBType 类型的值。如果这对您来说已经足够/足够了,那么您就没有什么可做的了。

如果您有任何机会需要返回值作为存储在接口(interface)值中的具体类型,您可以使用 type assertion .

例如:

a := StorageAType{Type:3}
b := TypeA3ToTypeB1(a) // b is of type StorageBType
if b1, ok := b.(StorageBType1); ok {
    // b1 is of type StorageBType1, you may use it like so:
    fmt.Println("b1.Type:", b1.Type)
} else {
    // b is not of type StorageBType1, or it is nil
}

输出:

b1.Type: 3

如果你想测试许多具体类型,你可以使用 type switch :

switch i := b.(type) {
    case nil:
        fmt.Println("nil")
    case StorageBType1:
        // Here i is of type StorageBType1, you may refer to its fields:
        fmt.Println("StorageBType1", i.Type)
    case StorageBType2:
        // Here i is of type StorageBType2, you may refer to its fields:
        fmt.Println("StorageBType2", i.Type, i.Name)
    default:
        fmt.Println("Unhandled type!")
}

关于go - 接口(interface)类型的函数返回(另一个)接口(interface)类型的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36788465/

相关文章:

c - 结构体 C 中变量矩阵的初始化

c++ - struct Node* 和 Node* 在函数调用上有什么区别?

go - 如何从 Golang 将控制台输入传递给子进程

go - "A"和 "A"的区别[0]

compilation - 手动编译 doozerd 失败

go - 通过 channel 传递的消息是否保证是非阻塞的?

c - 用函数修改 C 结构的子结构(用于 trie 的应用)

c++ - 结构数组的初始化

go - 为什么要使用 fmt.Sprint?

c - 两种不同类型的结构 - 需要动态地将一个传递给函数