There is an interface declaration and many structures that implement it
type datainterface interface { get(string) string } type dataa struct { d map[string]string } func (d *dataa) get(key string) string { return d.d[key] } func (d *dataa) getid() string { return d.get("id") } type datab struct { d map[string]string } func (d *datab) get(key string) string { return d.d[key] } func (d *datab) getfile() string { return d.get("file") } type datac...
Also includes datac,d,e...
I will store these datax
struct instances into type dataslice []datainterface
Now if I want to get datax
I can do this:
type dataslice []datainterface func (d dataslice) geta() []*dataa { var ret []*dataa for _, di := range d { if v, ok := di.(*dataa); ok { ret = append(ret, v) } } return ret } func (d dataslice) getb() []*datab { var ret []*datab for _, di := range d { if v, ok := di.(*datab); ok { ret = append(ret, v) } } return ret } func (d dataslice) getc() .....
Obviously there is a lot of duplicate code here:
var ret []*datax for _, di := range d { if v, ok := di.(*datax); ok { ret = append(ret, v) } }
So I thought I could use generics to solve this problem, then I defined this function:
func GetDataX[T any] (d DataInterface) *T { return d.(*T) }
But an error occurred: impossible type assertion: '*t' does not implement 'datainterface
So I want to know is this really impossible? Or can it be done some other way?
You should be able to use the following code to meet your needs:
package main import "fmt" // interface type DataInterface interface { Get(string) string } // struct implementing the interface type DataA struct { d map[string]string } func (d DataA) Get(key string) string { return d.d[key] } type DataB struct { d map[string]string } func (d DataB) Get(key string) string { return d.d[key] } type DataSlice []DataInterface func GetDataX[T any](d DataInterface) T { return d.(T) } func main() { a := DataA{map[string]string{"a": "1"}} b := DataB{map[string]string{"b": "2"}} ds := DataSlice{a, b} for _, v := range ds { if value, ok := v.(DataA); ok { fmt.Printf("A\t%q\n", GetDataX[DataA](value)) continue } if value, ok := v.(DataB); ok { fmt.Printf("B\t%q\n", GetDataX[DataB](value)) continue } // add unknown type handling logic here } }
First, I simplified the code to only consider the dataa
and datab
structures. I then changed the Pointer Receiver to a Value Receiver since you are not changing the state of the actual instance passed to the method. Because of this change, getdatax
works successfully and you can get all the information for similar structures.
If this solves your problem or you need something else, please let me know, thank you!
The above is the detailed content of How to convert an interface to a specified type using generics. For more information, please follow other related articles on the PHP Chinese website!