Golang - Reusing custom composable methods from structs around map type

83 views Asked by At

In the example shown on the image, I expected method Put to apply on MappingStringInt since it is composed from Mapping. However, this is not the case. If Mapping was composed with type struct, method Put will apply on MappingStringInt. Is there a way to fix this and make line 20 on the image to work? thanks

Golang - Reusing custom composable methods from structs around map type


package main

import "fmt"

type (
    Mapping[K comparable, V any] map[K]V
    MappingStringInt             Mapping[string, int]
)

func (self Mapping[K, V]) Put(key K, value V) Mapping[K, V] {
    self[key] = value
    return self
}
func main() {
    m1 := Mapping[string, int]{"two": 2}
    m1.Put("four", 4) // Works
    fmt.Printf("Mapping(four = %v) %+v \n", m1["four"], m1)

    m2 := MappingStringInt{"two": 2}
    m2.Put("four", 4) // Fails: m2.Put undefined (type MappingStringInt has no field or method Put)
    fmt.Printf("Mapping(four = %v) %+v \n", m2["four"], m2)
}

I tried using references on the method but it didn't work.

2

There are 2 answers

2
Jeet Chhatrala On

As Burak Serdar mentioned in comment, it will not be derived from the type but you can embed it in struct as below:

package main

import (
    "fmt"
)

type (
    Mapping[K comparable, V any] map[K]V

    MappingStringInt struct {
        Mapping[string, int]
    }
)

func (item Mapping[K, V]) Put(key K, value V) {
    item[key] = value
}

func main() {
    m1 := Mapping[string, int]{"two": 2}
    m1.Put("four", 4) // Works
    fmt.Printf("Mapping(four = %v) %+v \n", m1["four"], m1)

    m2 := MappingStringInt{Mapping: Mapping[string, int]{"two": 2}}
    m2.Put("three", 3)
    fmt.Printf("Mapping(four = %v) %+v \n", m2.Mapping["four"], m2)
}
3
Burak Serdar On

If you define a new type, the methods declared for the base type will not be available for the derived type. To use the methods declared for a type, you have to embed it into a new struct type.

One thing you can do is to use type aliases:

type MappingStringInt = Mapping[string, int]

Then, MappingStringInt is not a new type, but an alias for Mapping[string,int], and you can use them interchangeably.