Home > Backend Development > Golang > How to convert an interface to a specified type using generics

How to convert an interface to a specified type using generics

WBOY
Release: 2024-02-06 08:25:11
forward
1048 people have browsed it

How to convert an interface to a specified type using generics

Question content

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...
Copy after login

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() .....
Copy after login

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)
    }
}
Copy after login

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)
}
Copy after login

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?


Correct answer


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
    }
}
Copy after login

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!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template