Golang泛型在作为映射元素时无法正常工作。

huangapple go评论109阅读模式
英文:

Golang generic not working when used as map element

问题

我创建了一个MapKeys泛型和List泛型,但是当我将List泛型与普通的map[string]List[int]一起使用时,无法调用泛型的方法,我错在哪里?非常感谢任何想法!

泛型代码如下:

  1. package main
  2. import "fmt"
  3. func MapKeys[K comparable, V any](m map[K]V) []K {
  4. r := make([]K, 0, len(m))
  5. for k := range m {
  6. r = append(r, k)
  7. }
  8. return r
  9. }
  10. type List[T any] struct {
  11. head, tail *element[T]
  12. }
  13. type element[T any] struct {
  14. next *element[T]
  15. val T
  16. }
  17. func (lst *List[T]) Push(v T) {
  18. if lst.tail == nil {
  19. lst.head = &element[T]{val: v}
  20. lst.tail = lst.head
  21. } else {
  22. lst.tail.next = &element[T]{val: v}
  23. lst.tail = lst.tail.next
  24. }
  25. }
  26. func (lst *List[T]) GetAll() []T {
  27. var elems []T
  28. for e := lst.head; e != nil; e = e.next {
  29. elems = append(elems, e.val)
  30. }
  31. return elems
  32. }
  33. func main() {
  34. var m = map[int]string{1: "2", 2: "4", 4: "8"}
  35. fmt.Println("keys m:", MapKeys(m))
  36. _ = MapKeys[int, string](m)
  37. var yx = make(map[string]List[int])
  38. yx["one"] = List[int]{}
  39. yx["one"].Push(10)
  40. lst := List[int]{}
  41. lst.Push(10)
  42. lst.Push(13)
  43. lst.Push(23)
  44. fmt.Println("list:", lst.GetAll())
  45. }

调用这行代码:

  1. yx["one"].Push(10)

得到错误消息:

./prog.go:49:12: 无法在List[int]上调用指针方法Push

你可以在这里运行这段代码。

英文:

I created a MapKeys generic and List generic, but when using List generic with normal map[string]List[int], I can't call the generic's method, what I am wrong? any ideas will be very appreciated!

generic code like this :

  1. package main
  2. import "fmt"
  3. func MapKeys[K comparable, V any](m map[K]V) []K {
  4. r := make([]K, 0, len(m))
  5. for k := range m {
  6. r = append(r, k)
  7. }
  8. return r
  9. }
  10. type List[T any] struct {
  11. head, tail *element[T]
  12. }
  13. type element[T any] struct {
  14. next *element[T]
  15. val T
  16. }
  17. func (lst *List[T]) Push(v T) {
  18. if lst.tail == nil {
  19. lst.head = &element[T]{val: v}
  20. lst.tail = lst.head
  21. } else {
  22. lst.tail.next = &element[T]{val: v}
  23. lst.tail = lst.tail.next
  24. }
  25. }
  26. func (lst *List[T]) GetAll() []T {
  27. var elems []T
  28. for e := lst.head; e != nil; e = e.next {
  29. elems = append(elems, e.val)
  30. }
  31. return elems
  32. }
  33. func main() {
  34. var m = map[int]string{1: "2", 2: "4", 4: "8"}
  35. fmt.Println("keys m:", MapKeys(m))
  36. _ = MapKeys[int, string](m)
  37. var yx = make(map[string]List[int])
  38. yx["one"] = List[int]{}
  39. yx["one"].Push(10)
  40. lst := List[int]{}
  41. lst.Push(10)
  42. lst.Push(13)
  43. lst.Push(23)
  44. fmt.Println("list:", lst.GetAll())
  45. }

call this line :

  1. yx["one"].Push(10)

got the error message :

./prog.go:49:12: cannot call pointer method Push on List[int]

you can play the code here

答案1

得分: 2

List.Push()具有指针接收器,但您在映射中存储的是非指针,并且无法对映射进行索引取地址操作。详细信息请参见https://stackoverflow.com/questions/57321933/cannot-take-the-address-of-map-element/57322003#57322003。

在映射中存储指针,然后您可以在映射索引结果上调用具有指针接收器的方法:

  1. var yx = make(map[string]*List[int])
  2. yx["one"] = &List[int]{}
  3. yx["one"].Push(10)

Go Playground上尝试一下。

注意:如果值是可寻址的,例如变量,您可以在非指针值上调用具有指针接收器的方法:

  1. lst := List[int]{}
  2. lst.Push(10)

上述的lst.Push(10)(&lst).Push(10)的简写形式。详细信息请参见https://stackoverflow.com/questions/46956290/pointer-methods-on-non-pointer-types/46956348#46956348。

英文:

List.Push() has pointer receiver, but you store non-pointers in the map, and indexing maps is not addressable. For details see https://stackoverflow.com/questions/57321933/cannot-take-the-address-of-map-element/57322003#57322003.

Store pointers in the map, and then you can call methods with pointer receivers on map index results:

  1. var yx = make(map[string]*List[int])
  2. yx["one"] = &List[int]{}
  3. yx["one"].Push(10)

Try it on the Go Playground.

Note: you can call methods with pointer receiver on non-pointer values if the value is addressable, such as a variable:

  1. lst := List[int]{}
  2. lst.Push(10)

The above lst.Push(10) is a shorthand for (&lst).Push(10). For details see https://stackoverflow.com/questions/46956290/pointer-methods-on-non-pointer-types/46956348#46956348.

huangapple
  • 本文由 发表于 2022年8月19日 20:43:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/73416972.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定