Дженерики Голанга - простой вариант использования - PullRequest
0 голосов
/ 03 декабря 2018

Скажем, у меня есть 3 структуры:

type A struct{
   Foo map[string]string
}

type B struct{
   Foo map[string]string
}

type C struct{
   Foo map[string]string
}

, а затем я хочу создать функцию, которая может принимать любую из этих структур:

func handleFoo (){

}

Есть ли способ сделать этос Голангом?Примерно так:

type ABC = A | B | C

func handleFoo(v ABC){
   x: = v.Foo["barbie"] // this would be nice!
}

ОК, так что давайте попробуем интерфейс:

type FML interface {
  Bar() string
}

func handleFoo(v FML){
   z := v.Bar() // this will compile
   x: = v.Foo["barbie"] // this won't compile - can't access properties like Foo from v
}

На языке, который поощряет / заставляет составлять, я не могу понять, почему вы не можете получить доступ к таким свойствам, как Foo.

Ответы [ 3 ]

0 голосов
/ 03 декабря 2018

Вы можете использовать интерфейс таким образом, добавив метод GetFoo, чтобы получить foo для каждой структуры.

type A struct{
    Foo map[string]string
}

func(a *A) GetFoo() map[string]string {
    return a.Foo
}

type B struct{
    Foo map[string]string
}

func(b *B) GetFoo() map[string]string {
    return b.Foo
}

type C struct{
    Foo map[string]string
}

func(c *C) GetFoo() map[string]string {
    return c.Foo
}

type ABC interface {
    GetFoo() map[string][string]
}

func handleFoo (v ABC){
    foo := v.GetFoo()
    x:=foo["barbie"]
}
0 голосов
/ 03 декабря 2018

вы можете попробовать reflect и передать interface{} на handleFoo

https://play.golang.org/p/sLyjDvVrUjQ

https://golang.org/pkg/reflect/

package main

import (
    "fmt"
    "reflect"
)

func main() {
    type A struct {
        Foo map[string]string
    }
    type B struct {
        Foo map[string]int
    }
    type C struct {
        Foo map[string]uint
    }
    a := A{
        Foo: map[string]string{"a":"1"},
    }

    b := B{
        Foo: map[string]int{"a":2},
    }

    c := C {
        Foo: map[string]uint{"a":3},
    }


    fmt.Println(a, b, c)

    handleFoo(a)
    handleFoo(b)
    handleFoo(c)

    fmt.Println(a, b, c)
}



func handleFoo(s interface{}) {
    v := reflect.ValueOf(s)
    foo := v.FieldByName("Foo")
    if !foo.IsValid(){
        fmt.Println("not valid")
        return
    }

    switch foo.Type() {
    case reflect.TypeOf(map[string]string{}):
        fmt.Println("is a map[string]string")
        foo.Interface().(map[string]string)["a"] = "100"
    case reflect.TypeOf(map[string]int{}):
        fmt.Println("is a map[string]int")
        foo.Interface().(map[string]int)["a"] =  200
    case reflect.TypeOf(map[string]uint{}):
        fmt.Println("is a map[string]uint")
        foo.Interface().(map[string]uint)["a"] =  300
    }
}
0 голосов
/ 03 декабря 2018

Поскольку все A, B и C присваиваются одному и тому же базовому типу, вы можете использовать функцию с аргументом этого базового типа: func handleFoo(v struct{ Foo map[string]string })

Запустите его на игровой площадке .

Ограничением этого подхода является то, что методы на A, B и C (даже с одинаковыми именем и подписью) недоступны в handleFoo.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...