英文:
How to transfer interface to specified type by using generic
问题
这是一个声明接口和实现接口的多个结构体的代码示例。
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...
还包括`DataC,D,E...`等。
我将把这些`DataX`结构体的实例存储在`type DataSlice []DataInterface`中。
现在,如果我想获取`DataX`,可以这样做:
```go
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() .....
显然,这里有很多重复的代码:
var ret []*DataX
for _, di := range d {
if v, ok := di.(*DataX); ok {
ret = append(ret, v)
}
}
因此,我考虑使用泛型来解决这个问题,然后定义了这个函数:
func GetDataX[T any] (d DataInterface) *T {
return d.(*T)
}
但是出现了错误:Impossible type assertion: '*T' does not implement 'DataInterface'
。
所以,我想知道这种方式真的不可能吗?还是可以通过其他方式完成?
英文:
There is an Interface declare and many structs 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...
and I will store these DataX
structs instance into a 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's a lot of repetitive code here:
var ret []*DataX
for _, di := range d {
if v, ok := di.(*DataX); ok {
ret = append(ret, v)
}
}
So I think about that I can use generic to slove this, then I define this function:
func GetDataX[T any] (d DataInterface) *T {
return d.(*T)
}
but got error: Impossible type assertion: '*T' does not implement 'DataInterface
So, I want to know is this way really impossible? Or it could be completed by the other way?
答案1
得分: 1
你应该能够使用以下代码来满足你的需求:
package main
import "fmt"
// 接口
type DataInterface interface {
Get(string) string
}
// 实现接口的结构体
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
}
// 在这里添加未知类型的处理逻辑
}
}
首先,我简化了代码,只考虑了DataA
和DataB
结构体。然后,我将指针接收器更改为值接收器,因为你不会更改传递给方法的实际实例的状态。由于这个改变,GetDataX
成功工作,你可以获取所有类似结构体的信息。
如果这解决了你的问题,或者你需要其他帮助,请告诉我,谢谢!
英文:
You should be able to handle your needs with the following code:
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 take into consideration only the DataA
and DataB
structs. Then, I changed the pointer receivers to value receivers as you're not going to change the state of the actual instance passed to the methods. Thanks to this change the GetDataX
works successfully and you're able to get the info for all of your similar structs.
Let me know if this solves your issues or if you need something else, thanks!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论