我试图在两个存储器之间建立一个中间层,从存储器A取出,将其转换为相应类型的存储器B,然后存储它.由于我需要转换大约50-100种类型,我希望使用map [string] func并基于storageA.Type确定我需要调用哪个转换函数.
这些转换函数中的每一个都将返回不同的结构,所有结构都反映了存储B中的不同类型.这些存储B结构中的每一个都实现了一个公共接口,因此它们可以调用函数.
归结为我的问题是我无法将func(StorageAType)StorageBType1强制转换为func(StorageAType)StorageBType,即使StorageBtype1实现了接口StorageBType.
我已经创建了这个相当长的playground,因为我意识到用语言描述问题是棘手的.评论第38-41行和第60-63行将使它运行,但它是我想要使用的那些行.很抱歉它的大小,但我无法弄清楚一个不那么详细而又清晰的例子.
请注意,我必须重新创建我的stackoverflow帐户,所以我不认为我有代表评论答案.
*编辑:
非常典型.在询问之后我意识到如何解决它.通过返回转换器函数中的接口类型而不是在playground中进行更改的确切类型.
最佳答案 具有不同结果类型的函数类型是不同的类型,如果其中一个结果类型实现另一个,则无关紧要.
Spec: Function types:
A function type denotes the set of all functions with the same parameter and result types.
StorageBtype1和StorageBType是不同的类型,因此将它们作为结果类型的函数类型也不同,并且这些函数类型之一的值不能用作另一个的值.
只需将所有转换器函数的结果类型更改为StorageBType:
func TypeA3ToTypeB1(i StorageAType) StorageBType {
return StorageBType1{i.Type}
}
func TypeA5ToTypeB2(i StorageAType) StorageBType {
return StorageBType2{i.Type, i.Name}
}
由于所有返回值都实现了StorageBType,因此这是一个有效的更改,并且不需要更改转换器函数的实现.
现在调用这些函数当然会返回StorageBType类型的值.如果这对您来说足够/足够,您就没有其他任何事情可做了.
如果您有可能需要返回值作为存储在接口值中的具体类型,则可以使用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!")
}