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)
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With