繁体   English   中英

如何为可以使用 len() 的东西编写 Go 类型约束?

[英]How to write a Go type constraint for something you can take len() of?

我正在尝试为 Go 程序编写一个类型约束,它接受“任何你可以接受 len() 的东西”。 但我真的想不通。

我想要这样的东西:

LenOf[m Measurable](m M) int {
    return len(m)
}

我尝试了一些东西。 外汇。 这个幼稚的东西,确实可以编译,但不适用于所有类型(比如 fx []User ):

type Measurable interface {
    ~string | []any | ~map[any]any
}

然后继续类似下面的事情,它不仅使LenOf()的 function 签名非常笨拙,而且在调用站点上写起来也很笨拙(而且仍然无法编译)

type Measurable[K comparable, V any] interface {
   ~string | []V | ~map[K]V
}

为什么? 内置len已经是“通用的”。


话虽如此,让我们看看为什么定义这样的约束是个坏主意。 Go 规范中有一段 — Length and capacity ,可以帮助:

如果参数类型是类型参数 P,则调用len(e) (或分别为cap(e)必须对 P 的类型集中的每个类型都有效 结果是参数的长度(或容量),其类型对应于 P 被实例化的类型参数。

为“可测量”类型编写包罗万象的约束的问题是:

  • 它包括 arrays [N]T ,其中数组长度是类型的一部分,因此您的约束必须指定您要捕获的所有可能的 arrays
  • 它包括数组指针*[N]T ,您不能在类型约束中轻易抽象它
  • 它包括映射,这会强制您捕获键K和值V ,它们可能与T相同也可能不同。 另外, K必须实现comparable

所以你必须写这样的东西:

type Measurable[T any, K comparable, V any] interface {
    ~string | ~[]T | ~map[K]V | ~chan T
}

其中明显不包括 arrays,并且没有明确捕获指针文字,例如要匹配[]*int ,您必须使用*int实例化T

您可以简化V

type Measurable[T any, K comparable] interface {
    ~string | ~[]T | ~map[K]T | ~chan T
}

function LenOf则变为:

func LenOf[T any, K comparable, M Measurable[T, K]](m M) int {
    return len(m)
}

但您仍然必须提供K ,因此您必须在呼叫站点使用 map 密钥的伪造类型实例化LenOf

LenOf[string, int]("foo")
//            ^ actually useless

并且您也不能利用参数的类型推断。

总之:只需使用len 设计您的泛型函数以使用支持长度的类型字面量,或者仅将您的函数理应处理的那些类型添加到约束中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM