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

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

Golang generic not working when used as map element

问题

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

泛型代码如下:

package main

import "fmt"

func MapKeys[K comparable, V any](m map[K]V) []K {
	r := make([]K, 0, len(m))
	for k := range m {
		r = append(r, k)
	}
	return r
}

type List[T any] struct {
	head, tail *element[T]
}

type element[T any] struct {
	next *element[T]
	val  T
}

func (lst *List[T]) Push(v T) {
	if lst.tail == nil {
		lst.head = &element[T]{val: v}
		lst.tail = lst.head
	} else {
		lst.tail.next = &element[T]{val: v}
		lst.tail = lst.tail.next
	}
}

func (lst *List[T]) GetAll() []T {
	var elems []T
	for e := lst.head; e != nil; e = e.next {
		elems = append(elems, e.val)
	}
	return elems
}

func main() {
	var m = map[int]string{1: "2", 2: "4", 4: "8"}

	fmt.Println("keys m:", MapKeys(m))

	_ = MapKeys[int, string](m)

	var yx = make(map[string]List[int])
	yx["one"] = List[int]{}
	yx["one"].Push(10)

	lst := List[int]{}
	lst.Push(10)
	lst.Push(13)
	lst.Push(23)
	fmt.Println("list:", lst.GetAll())
}

调用这行代码:

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 :

package main
import "fmt"
func MapKeys[K comparable, V any](m map[K]V) []K {
r := make([]K, 0, len(m))
for k := range m {
r = append(r, k)
}
return r
}
type List[T any] struct {
head, tail *element[T]
}
type element[T any] struct {
next *element[T]
val  T
}
func (lst *List[T]) Push(v T) {
if lst.tail == nil {
lst.head = &element[T]{val: v}
lst.tail = lst.head
} else {
lst.tail.next = &element[T]{val: v}
lst.tail = lst.tail.next
}
}
func (lst *List[T]) GetAll() []T {
var elems []T
for e := lst.head; e != nil; e = e.next {
elems = append(elems, e.val)
}
return elems
}
func main() {
var m = map[int]string{1: "2", 2: "4", 4: "8"}
fmt.Println("keys m:", MapKeys(m))
_ = MapKeys[int, string](m)
var yx = make(map[string]List[int])
yx["one"] = List[int]{}
yx["one"].Push(10)
lst := List[int]{}
lst.Push(10)
lst.Push(13)
lst.Push(23)
fmt.Println("list:", lst.GetAll())
}

call this line :

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。

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

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

Go Playground上尝试一下。

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

lst := List[int]{}
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:

var yx = make(map[string]*List[int])
yx["one"] = &List[int]{}
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:

lst := List[int]{}
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:

确定