Home > Back-end >  Golang generic not working when used as map element
Golang generic not working when used as map element

Time:08-20

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

CodePudding user response:

List.Push() has pointer receiver, but you store non-pointers in the map, and indexing maps is not addressable. For details see Cannot take the address of map element.

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 Pointer methods on non pointer types.

  • Related