Я новичок, все еще нахожусь на этапе обучения и не смог найти ответов, соответствующих моей проблеме, поэтому, пожалуйста, не ставьте минус.
У меня есть общий интерфейс, экземпляр которого можно создать с помощью двух параметров типа, и у меня нет абсолютно никаких проблем с созданием новых карт с типами, реализующими этот интерфейс. Я также могу вставлять и индексировать ключи, но столкнулся с проблемой при попытке вернуть значения с карт с помощью общей функции. Пожалуйста, помогите мне исправить функцию GetGenericIfaceVal
, упомянутую ниже. Компилятор жалуется, что не может вернуть тип c, поскольку это IncompatibleAssign
.
package main
import (
"strings"
)
type GenericIface[rType ~map[string]T, T interface{}] interface {
GetSubTypes() rType
}
type t1 struct {
subTypes r1
}
type r1 map[string]r1
type t2 struct {
subTypes r2
}
type r2 map[string]t2
var mapFirst = make(map[string]GenericIface[r1, r1])
var mapSecond = make(map[string]GenericIface[r2, t2])
//cannot use mapFirst[cType] (map index expression of type GenericIface[r1, r1]) as c value in return statement compiler (IncompatibleAssign) [29, 12]
func GetGenericIfaceVal[c GenericIface[M, T],M ~map[string]T, T interface{}](cType string) c {
if strings.HasPrefix(cType, "$") {
return mapFirst[cType]
}
return mapSecond[cType]
}
func (t *t1) GetSubTypes() r1 {
return t.subTypes
}
func (t *t2) GetSubTypes() r2 {
return t.subTypes
}
При работе с дженериками, особенно в go, все становится сложнее. Нам нужно осторожно обращаться со сложными ограничениями типов. В вашем случае проблема, похоже, связана с ограничениями типов и возвращаемыми значениями функции. Вот как вы можете справиться с этим:
package main
import (
"fmt"
"strings"
)
type GenericIface[M ~map[string]T, T any] interface {
GetSubTypes() M
}
type t1 struct {
subTypes r1
}
type r1 map[string]r1
type t2 struct {
subTypes r2
}
type r2 map[string]t2
var mapFirst = make(map[string]GenericIface[r1, r1])
var mapSecond = make(map[string]GenericIface[r2, t2])
GenericIface[r2, t2] based on the input type.
func GetGenericIfaceVal[M ~map[string]T, T any](cType string) GenericIface[M, T] {
if strings.HasPrefix(cType, "$") {
return mapFirst[cType].(GenericIface[M, T])
}
return mapSecond[cType].(GenericIface[M, T])
}
interface.
func (t *t1) GetSubTypes() r1 {
return t.subTypes
}
func (t *t2) GetSubTypes() r2 {
return t.subTypes
}
func main() {
mapFirst["$example"] = &t1{subTypes: make(r1)}
mapSecond["example"] = &t2{subTypes: make(r2)}
val1 := GetGenericIfaceVal[r1, r1]("$example")
fmt.Printf("val1: %T\n", val1)
val2 := GetGenericIfaceVal[r2, t2]("example")
fmt.Printf("val2: %T\n", val2)
}
Вам не хватало утверждения типа. Это связано с тем, как Go обрабатывает параметры типов и интерфейсы, особенно с дженериками.
https://www.freecodecamp.org/news/generics-in-golang/
https://callistaenterprise.se/blogg/teknik/2022/05/30/go-generics-in-functional-style/
https://programmingpercy.tech/blog/learning-generics-in-go/
https://thewikihow.com/video_Eor1w37tVNw
Спасибо! Я проголосовал за это. И последний вопрос: не могли бы вы поделиться ссылкой, где я мог бы подробно прочитать об этом? Тогда я обязательно отмечу это как правильный ответ.
Я добавил статьи и видео, где вы можете подробно узнать об этом.
Понятно, поэтому нам нужно было ввести утверждения. Не могли бы вы немного рассказать, почему без утверждений это не работает?