Go泛型中V类型值直接比较失败,转为any后正常的原因咨询
Go泛型中值比较的问题解析
使用Go 1.21rc2编写泛型函数时,遇到了值比较的差异问题:判断某个值是否存在于map的values集合中,版本1代码编译失败,转为any类型后的版本2可正常运行,具体原因如下:
版本1(编译失败)
func InValues[M ~map[K]V, K comparable, V any](m M, v V) bool { for _, x := range maps.Values(m) { if x == v { return true } } return false }
版本2(正常运行)
func InValues[M ~map[K]V, K comparable, V any](m M, v V) bool { for _, x := range maps.Values(m) { if any(x) == any(v) { return true } } return false }
核心原因解析
泛型约束的限制
版本1中V的约束是any,这意味着V可以被实例化为任意类型,包括切片、map、函数这类不可比较类型。Go的类型系统要求只有可比较类型才能使用==比较,编译器无法保证V实例化后一定是可比较类型,因此x == v会直接触发编译错误。接口值比较的特性
版本2中把x和v转为any(即interface{})后,进行的是接口值的比较:- 接口值本身属于可比较类型,编译器允许这类比较操作;
- 比较时先检查两个接口值的类型是否一致,类型不同则直接返回不等;
- 类型一致的情况下,再比较底层的值——如果底层类型是不可比较类型(比如切片),会在运行时触发panic,但编译阶段不会报错。
优化建议
如果希望在编译阶段就拦截不可比较类型的传入,避免运行时panic,可以将V的约束改为comparable,版本1的代码即可正常运行:
func InValues[M ~map[K]V, K comparable, V comparable](m M, v V) bool { for _, x := range maps.Values(m) { if x == v { return true } } return false }
内容的提问来源于stack exchange,提问作者Sam Wood
相关产品推荐
相关产品推荐

