英文:
Return different specialised implementations of interfaces from the same function
问题
我有几个数据结构,它们之间有一些相似但具有各自独特字段的特点。它们都实现了相同的行为接口(DataPoint)。因此,可以通过在接口定义的方法上操作并交换每个结构的类型来进行它们的处理。我想要一个函数根据某些条件为每种类型返回一个空的数据结构。然而,如果我的函数按照接口的签名返回接口,但实际上返回的是一个实现,编译器会报错。
这里是一个简化的示例和Playground样例,展示了我的意思:
package main
import "fmt"
type DataPoint interface {
Create()
}
type MetaData struct {
UniqueId string
AccountId int
UserId int
}
type Conversion struct {
Meta MetaData
Value int
}
func (c *Conversion) Create() {
fmt.Println("CREATE Conversion")
}
type Impression struct {
Meta MetaData
Count int
}
func (i *Impression) Create() {
fmt.Println("CREATE Impression")
}
func getDataPoint(t string) DataPoint {
if t == "Conversion" {
return &Conversion{}
} else {
return &Impression{}
}
}
func main() {
meta := MetaData{
UniqueId: "ID123445X",
AccountId: 1,
UserId: 2,
}
dpc := getDataPoint("Conversion")
dpc.Meta = meta
dpc.Value = 100
dpc.Create()
fmt.Println(dpc)
dpi := getDataPoint("Impression")
dpi.Meta = meta
dpi.Count = 42
dpi.Create()
fmt.Println(dpi)
}
编译产生以下错误:
prog.go:51: dpc.Meta undefined (type DataPoint has no field or method Meta)
prog.go:52: dpc.Value undefined (type DataPoint has no field or method Value)
prog.go:58: dpi.Meta undefined (type DataPoint has no field or method Meta)
prog.go:59: dpi.Count undefined (type DataPoint has no field or method Count)
英文:
I'm have a few data structures which are similar with some unique fields to each. They all implement the same behavioural interface (DataPoint).
Therefore their processing can be done once while exchanging the type of each structure and operating on it via the methods defined in the interface. I wanted to have a function return me the empty data struct for each type based on some criteria.
However, I can't seem to compile this as if my function returns the interface by signature but actually returns an implementation, it complains.
Here's a simplified example and playground sample of what I mean:
https://play.golang.org/p/LxY55BC59D
package main
import "fmt"
type DataPoint interface {
Create()
}
type MetaData struct {
UniqueId string
AccountId int
UserId int
}
type Conversion struct {
Meta MetaData
Value int
}
func (c *Conversion) Create() {
fmt.Println("CREATE Conversion")
}
type Impression struct {
Meta MetaData
Count int
}
func (i *Impression) Create() {
fmt.Println("CREATE Impression")
}
func getDataPoint(t string) DataPoint {
if t == "Conversion" {
return &Conversion{}
} else {
return &Impression{}
}
}
func main() {
meta := MetaData{
UniqueId: "ID123445X",
AccountId: 1,
UserId: 2,
}
dpc := getDataPoint("Conversion")
dpc.Meta = meta
dpc.Value = 100
dpc.Create()
fmt.Println(dpc)
dpi := getDataPoint("Impression")
dpi.Meta = meta
dpi.Count = 42
dpi.Create()
fmt.Println(dpi)
}
The compilation produces:
prog.go:51: dpc.Meta undefined (type DataPoint has no field or method Meta)
prog.go:52: dpc.Value undefined (type DataPoint has no field or method Value)
prog.go:58: dpi.Meta undefined (type DataPoint has no field or method Meta)
prog.go:59: dpi.Count undefined (type DataPoint has no field or method Count)
答案1
得分: 7
你可以使用类型断言(type assertion)来访问这样的字段。你只能在接口上调用方法,它对实现细节一无所知。如果你确实需要访问这些字段,可以使用类型断言:
dpc := getDataPoint("Conversion")
dpc.(*Conversion).Meta = meta
dpc.(*Conversion).Value = 100
dpc.Create()
dpi := getDataPoint("Impression")
dpi.(*Impression).Meta = meta
dpi.(*Impression).Count = 42
dpi.Create()
Playground: https://play.golang.org/p/Ije8hfNcWS。
英文:
You can't access fields like that without a type assertion. You can only call methods on the interface, it doesn't know anything about its implementation details. If you do need to access those fields, use a type assertion:
dpc := getDataPoint("Conversion")
dpc.(*Conversion).Meta = meta
dpc.(*Conversion).Value = 100
dpc.Create()
dpi := getDataPoint("Impression")
dpi.(*Impression).Meta = meta
dpi.(*Impression).Count = 42
dpi.Create()
Playground: https://play.golang.org/p/Ije8hfNcWS.
答案2
得分: 3
你的问题是getDataPoint
的结果是一个DataPoint
,它只有一个可用的方法:Create
。然后你尝试将其用作特定的结构类型,这些结构类型恰好提供了所有的元数据字段。
你可以让DataPoint
接口提供一个MetaData
函数或类似的方法,或者在字段上提供单独的getter方法。如果MetaData
类型实现了这些方法,当将其作为接口本身呈现时,这些方法将在任何特定的结构体中都可用。
英文:
Your issue is that the result from getDataPoint
is a DataPoint
, which only has one method available: Create
. You then try to use it as the specific struct types, which incidentally provide all of the metadata fields.
You could have your DataPoint interface provide a MetaData
function or something like that, or individual getters on the fields. If the MetaData
type implements those methods they will be available from either of the specific structs when presented as the interface itself.
答案3
得分: 2
你的函数getDataPoint返回一个接口,而不是一个结构体。所以如果你想将其返回值用作结构体,你必须先进行类型断言。这里是一个可工作的代码示例:
https://play.golang.org/p/5lx4BLhQBg
英文:
Your function getDataPoint returns an interface, not a struct. So if you want to use its return value as a struct, you must do a type assertion first. Here is a working code :
https://play.golang.org/p/5lx4BLhQBg
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论