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

标签 go generics types

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

我想要这样的东西:

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

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

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

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

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

最佳答案

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


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

If the argument type is a type parameter P, the call len(e) (or cap(e) respectively) must be valid for each type in P's type set. The result is the length (or capacity, respectively) of the argument whose type corresponds to the type argument with which P was instantiated.

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

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

所以你必须这样写:

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

值得注意的是不包括数组,也没有明确地捕获指针文字,例如要匹配 []*int,您必须使用 *int 实例化 T

你可以简化V:

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

函数 LenOf 则变为:

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

但您仍然需要提供 K,因此您必须在调用站点用伪造的映射键类型实例化 LenOf:

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

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

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

关于go - 如何为可以使用 len() 的东西编写 Go 类型约束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74538708/

相关文章:

Golang “net/http” DetectContentType 错误

string - 为什么 string.Replace 在 golang 中不起作用

c# - 如何使用反射找到特定的通用重载?

c# - 通用表<TEntity>

android - 根据序列号/唯一 ID 确定设备类型

scala - 扩展另一个结构类型的结构类型

go - 为什么反射要与 UNEXPORTED Struct 和 Unexported Fields 一起使用?

Golang 工作区实践

java - 日志记录的通用方法

C# 如何将对象列表传递给构造函数?