可以编写一个约束来排除某种类型吗?

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

Is it possible to write a constraint to exclude a type?

问题

  1. type NonString interface {
  2. // ???
  3. }
  4. func MyFunc[T NonString](v T) T {
  5. return v
  6. }
  7. func main() {
  8. MyFunc(1) // OK
  9. MyFunc(false) // OK
  10. MyFunc([]string{}) // OK
  11. MyFunc("hi, boy!") // 我希望在这里发生编译错误!
  12. }

上述代码中的注释描述了我想要的情况。

在 Golang 中是否可能实现这个要求?


原始场景

我有两个函数如下:

  1. func Any2String(v any) string {
  2. return fmt.Sprint(v) // 慢速版本
  3. }
  4. func Integer2String[N Integer](v N) string {
  5. return strconv.FormatInt(int64(v), 10) // 快速版本
  6. }

Any2String(v) 可以将任何 v 转换为字符串。然而,如果 v 是整数,Integer2String(v) 的速度要快得多。

因此,我希望编译器在适用更快的 Integer2String(v) 的情况下,阻止我调用 Any2String(v)

英文:
  1. type NonString interface {
  2. // ???
  3. }
  4. func MyFunc[T NonString](v T) T {
  5. return v
  6. }
  7. func main() {
  8. MyFunc(1) // OK
  9. MyFunc(false) // OK
  10. MyFunc([]string{}) // OK
  11. MyFunc("hi, boy!") // I hope a comiler error occurs here!
  12. }

What I want is decribed in the comments of the code above.

Is it possible in golang?


Original Scenario

I have two functions as follows:

  1. func Any2String(v any) string {
  2. return fmt.Sprint(v) // Slow version
  3. }
  4. func Integer2String[N Integer](v N) string {
  5. return strconv.FormatInt(int64(v), 10) // Fast version
  6. }

Any2String(v) can convert any v to a string. However, if v is an integer, Integer2String(v) is much more faster.

So, I want the compiler to PREVENT me from calling Any2String(v) when the faster Integer2String(v) is applicable.

答案1

得分: 1

不,这是不可能的。约束类型集不能表示为集合的减法。

可以定义无法满足任何类型的约束,例如:

  1. type NotSatisfiable interface {
  2. int
  3. foo()
  4. }

这个约束要求一个类型完全是int类型,并且有一个名为foo()的方法。由于无法在预声明的类型上定义方法,因此无法满足这个约束。

然而,你不能定义像"any-minus-int"或"any-plus-NotSatisfiable"这样的约束。

如果你有一个函数对除了少数几种类型之外的任何类型都能正常工作,只需使用类型切换:

  1. func ToString(v any) string {
  2. switch t := v.(type) {
  3. case int:
  4. return Integer2String(t)
  5. default:
  6. return Any2String(t)
  7. }
  8. }

你甚至不需要泛型,因为类型为any的普通参数完全可以胜任。

英文:

No, it's not possible. Constraint type sets cannot be expressed as set subtraction.

It is possible to define constraints that can't be satisfied by any type, for example:

  1. type NotSatisfiable interface {
  2. int
  3. foo()
  4. }

This constraint mandates a type that is exactly int and that has a method foo(). Since you can't define methods on predeclared types, it's not possible to satisfy this constraint.

However you can't define a constraint like "any-minus-int" or "any-plus-NotSatisfiable".

If you have a function that works exactly the same for any type except a discrete number of types, just use a type switch:

  1. func ToString(v any) string {
  2. switch t := v.(type) {
  3. case int:
  4. return Integer2String(t)
  5. default:
  6. return Any2String(t)
  7. }
  8. }

You don't even need generics, because a regular argument of type any works just fine.

huangapple
  • 本文由 发表于 2023年6月13日 18:10:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76463823.html
匿名

发表评论

匿名网友

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

确定