在其他泛型类型中使用具有setter方法的约束

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

Constraint with setter methods to be used in other generic types

问题

我正在使用golang泛型进行实验,尝试在所有mongo集合上实现CRUD操作,但是在尝试直接在结构体上更新某些字段时遇到了问题,我得到了一个错误。

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没有实现TModel(SetName方法具有指针接收器)

我尝试将func(s *MyUser)更改为func (s MyUser),但是结构体没有反映出更改。

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

英文:

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

答案1

得分: 2

你在接口中设置了一个类型约束:

type TModel interface {
    MyUser | AnotherModel
    ...
}

因此,你不能将*MyUser作为TModel的类型参数。


要修复编译时错误:更改类型约束

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

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


额外的备注:除非你有特殊动机要明确列出可以用作TModel的唯一类型,否则我认为

type TModel interface {
    SetName(s string)
}

对于你的泛型类型来说可能已经足够了。

英文:

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.

huangapple
  • 本文由 发表于 2022年6月15日 16:33:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/72628205.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定