Home > Blockchain >  Constraint with setter methods to be used in other generic types
Constraint with setter methods to be used in other generic types

Time:06-16

I'm playing with golang generics, trying to implement CRUD operations over all the mongo collections, but I'm facing issues trying to update some fields directly on the struct but I'm getting an error

package main

import (
    "fmt"
)

type TModel interface {
    MyUser | AnotherModel
    SetName(string)
}

type MyUser struct {
    ID   string `bson:"_id"`
    Name string `bson:"name"`
}

type AnotherModel struct {
    ID   string `bson:"_id"`
    Name string `bson:"name"`
}

// Using this function compiles, but never update the struct
func (s MyUser) SetName(name string) {
    s.Name = name
}

/*This should be the right way, but fails at compile time */
/*
func (s *MyUser) SetName(name string) {
    s.Name = name
}
*/

type Crud[model TModel] interface {
    UpdateObj(m model) (*model, error)
}

type CrudOperations[model TModel] struct {
}

func (c *CrudOperations[model]) UpdateObj(m model) error {
    fmt.Printf("\n  Obj: %v", m)
    m.SetName("NewName")
    fmt.Printf("\n  Obj: %v", m)
    return nil
}

func main() {
    c := CrudOperations[MyUser]{}
    m := MyUser{Name: "Initial-Name"}
    c.UpdateObj(m)

}

./prog.go:44:22: MyUser does not implement TModel (SetName method has pointer receiver)

I tried changing from func(s *MyUser) to func (s MyUser) but then the struct is not reflecting the change

ineffective assignment to field MyUser.Name (staticcheck)

Playground: https://go.dev/play/p/GqKmu_JfVtC

CodePudding user response:

You put a type constaint :

type TModel interface {
    MyUser | AnotherModel
    ...

in your interface, so you can't use a *MyUser as a type parameter for TModel


To fix your compile time error : change the type constraint

type TModel interface {
    *MyUser | *AnotherModel
    ...
}

https://go.dev/play/p/1oP2LzeqXIa


one extra remark : unless you have an ulterior motive to explicitly list the only types that can ever be used as a TModel, I would say that

type TModel interface {
    SetName(s string)
}

is probably enough of a constraint for your generic type.

  • Related