-1

I'm just now starting to work with generics for a project. I've set up the following example in a go playground. I'm trying to create a generic function to reset the cache of 2 different types, that have the same fields. Furthermore, I can't figure out why I can't access those fields withing the generic function.

The error is:

./prog.go:21:4: c.Count undefined (type *C is pointer to type parameter, not type parameter)
./prog.go:22:4: c.List undefined (type *C is pointer to type parameter, not type parameter)

Any help is appreciated.

https://go.dev/play/p/ojkNe1D-hSE

package main

import "fmt"

type CacheOne struct {
    Count int
    List  []string
}

type CacheTwo struct {
    Count int
    List  []string
}

type cachable interface {
    CacheOne | CacheTwo
}

// resetSCache resets the Count & List of a given cachable type.
func resetCache[C cachable](c *C) {
    c.Count = 0
    c.List = []string{}
}

func main() {
    // Example usage
    dOne := &CacheOne{
        Count: 5,
        List:  []string{"hello", "world"},
    }
    dTwo := &CacheTwo{
        Count: 5,
        List:  []string{"hello", "world"},
    }

    fmt.Println("Before reseting...whould be populated with data")
    fmt.Println(dOne)
    fmt.Println(dTwo)

    resetCache(dOne)
    resetCache(dTwo)

    fmt.Println("Before reseting...whould be reset with zero values")
    fmt.Println(dOne)
    fmt.Println(dTwo)
}
ENG618
  • 1,012
  • 1
  • 13
  • 31

1 Answers1

1

what you're trying to achieve is not permitted by Go as of now. You can find more details in this answer link. Probably something could change in the future but AFAIK, you've to stick to the following implementation:

package main

import "fmt"

type CacheOne struct {
    Count int
    List  []string
}

type CacheTwo struct {
    Count int
    List  []string
}

type cachable interface {
    SetCount(count int)
    SetList([]string)
}

func (c *CacheOne) SetCount(count int) {
    c.Count = count
}

func (c *CacheOne) SetList(list []string) {
    c.List = list
}

func (c *CacheTwo) SetCount(count int) {
    c.Count = count
}

func (c *CacheTwo) SetList(list []string) {
    c.List = list
}

// resetSCache resets the Count & List of a given cachable type.
func resetCache[C cachable](c C) {
    c.SetCount(0)
    c.SetList(make([]string, 0))
}

func main() {
    // Example usage
    dOne := &CacheOne{
        Count: 5,
        List:  []string{"hello", "world"},
    }
    dTwo := &CacheTwo{
        Count: 5,
        List:  []string{"hello", "world"},
    }

    fmt.Println("Before reseting...whould be populated with data")
    fmt.Println(dOne)
    fmt.Println(dTwo)

    resetCache(dOne)
    resetCache(dTwo)

    fmt.Println("Before reseting...whould be reset with zero values")
    fmt.Println(dOne)
    fmt.Println(dTwo)
}

If you run this code, you should get the desired output:

Before reseting...whould be populated with data
&{5 [hello world]}
&{5 [hello world]}
Before reseting...whould be reset with zero values
&{0 []}
&{0 []}

I agree that this method could be a little cumbersome but it's what is :)
If you find a smarter way to achieve just let me know in case.
I hope that this helps you in solving your issue, thanks!

ossan
  • 1,665
  • 4
  • 10
  • 1
    Thanks for the details. That was kinda the conclusion that I came to, but was hopping I was wrong! – ENG618 Jun 09 '23 at 16:25