有没有一种方法可以检查一个值是否满足接口中定义的类型约束?

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

Is there a way to check if value satisfies type constraint defined in interface?

问题

例如,我定义了以下接口:

type MyTypeConstraint interface {
    ~int | ~string
}

除了使用switch reflect.TypeOf(v)语句将值与MyTypeConstraint中的每个类型进行比较之外,还有其他方法可以检查给定值是否满足此约束吗?例如,在这里,我不希望用户将不满足约束的类型的v传递给函数:

type ErrNode struct {
	Data map[string]interface{}
	// Err  error -- 不相关
	// next *ErrNode -- 不相关
}

// `GetData()` 受约束,但 `Set()` 不受约束。
// 当然,我可以将 `ErrNode` 作为参数传递给 `Set()`,
// 但这样我就无法链式调用 `Set()`。
func GetData[T ErrData](list *ErrNode, k string) (v T, ok bool) {
	v, ok = list.Data[k].(T)
	return v, ok
}

func (e *ErrNode) Set(k string, v interface{}) (self *ErrNode) {
	e.Data[k] = v // v 必须是 `MyTypeConstraint` 中列出的类型之一
	return e
}
英文:

For example I defined the following interface:

type MyTypeConstraint interface {
    ~int | ~string
}

Is there a way to check if given value satisfies this constraint aside from comparing value to each type inside MyTypeConstraint using switch reflect.TypeOf(v) statement? For example, here I don't want user to pass v which type doesn't satisfy constraint into function:

type ErrNode struct {
	Data map[string]interface{}
	// Err  error -- irrelevant
	// next *ErrNode -- irrelevant
}

// `GetData()` is constrained but `Set()` is not.
// Of course I could pass `ErrNode` as parameter into `Set()` 
// like bellow but then I won't be able to chain `Set()` calls.
func GetData[T ErrData](list *ErrNode, k string) (v T, ok bool) {
	v, ok = list.Data[k].(T)
	return v, ok
}

func (e *ErrNode) Set(k string, v interface{}) (self *ErrNode) {
	e.Data[k] = v // v must be of type listed in `MyTypeConstraint`
	return e
}

答案1

得分: 1

你不能在方法上使用类型约束(至少在go1.181.19版本中是这样的):

// 语法错误:方法不能有类型参数
func (e *ErrNode) Set[T MyTypeConstraint](k string, v T) (self *ErrNode) {
    e.Data[k] = v
    return e
}

但你可以在函数上使用类型约束:

func Setter[T MyTypeConstraint](e *ErrNode, k string, v T) {
    e.Data[k] = v
}

go 1.18发布说明中可以看到,他们希望在将来的版本中移除这个限制。然而,截至go 1.19,仍然不允许这样做:

Go编译器只支持在类型参数类型P的值x上调用方法m,如果m是P的约束接口明确声明的。类似地,方法值x.m和方法表达式P.m也只支持m是P明确声明的情况,即使m可能通过P的所有类型实现而在P的方法集中。我们希望在将来的版本中移除这个限制。

英文:

You cannot (at least with go 1.18 or 1.19 *) put a type constraint on a method:

//syntax error: method must have no type parameters

func (e *ErrNode) Set[T MyTypeConstraint](k string, v T) (self *ErrNode) {
	e.Data[k] = v
	return e
}

You may put a type constraint on a function:

func Setter[T MyTypeConstraint](e *ErrNode, k string, v T) {
	e.Data[k] = v
}

(*) from the go 1.18 release notes: We hope to remove this restriction in a future release. - and this still is not allowed as of go 1.19:

> The Go compiler only supports calling a method m on a value x of type
> parameter type P if m is explicitly declared by P's constraint
> interface. Similarly, method values x.m and method expressions P.m
> also are only supported if m is explicitly declared by P, even though
> m might be in the method set of P by virtue of the fact that all types
> in P implement m. We hope to remove this restriction in a future
> release.

huangapple
  • 本文由 发表于 2022年8月1日 23:05:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/73195780.html
匿名

发表评论

匿名网友

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

确定