你如何编写一个允许指向多个原始类型的指针的通用 Go 函数?
How do you write a generic Go function that allows pointers to multiple primitive types?
我正在尝试使用 Go 泛型编写一个函数来减少我们代码中的一些样板 if/else 块。我想出了 something that works for a single type parameter 如下:
func valueOrNil[T *int](value T) any {
if value == nil {
return nil
}
return *value
}
虽然这工作正常,但它并不是很有用,因为它只允许 *int
,而且我希望这段代码适用于任何原始类型。我试图扩展它以支持第二种类型,as follows:
func valueOrNil[T *int | *uint](value T) any {
if value == nil {
return nil
}
return *value
}
但是,此变体因编译器错误而失败:
invalid operation: pointers of value (variable of type T constrained by *int|*uint) must have identical base types
任何人都可以发现我在这里做错了什么,或者像这样的东西只是“不受支持”吗?
问题似乎在于您试图通过 指向类型的指针 而不是 类型本身 来实现通用。如果我们将指针移动到参数本身而不是类型参数上,它就可以工作。
解释如下,但这里是工作代码:
func valueOrNil[T ~int | ~uint](value *T) T {
if value == nil {
var zero T
return zero
}
return *value
}
所以不是这个(这是行不通的):
func valueOrNil[T *int | *uint](value T) any
你可以这样做:
func valueOrNil[T int | uint](value *T) any
但是,您可能希望更进一步并处理基础类型:
func valueOrNil[T ~int | ~uint](value *T) any
这将允许自定义类型与函数一起使用:
type Thing int
var thing Thing
println(valueOrNil(thing))
您可能要考虑的另一个方面是 return 类型的通用性。您可以使用相同的 T
参数。
例如:
func valueOrNil([T ~int | ~uint](value *T) T
但这意味着您需要更改部分实现。而不是这个:
if value == nil {
return nil
}
你可以这样做:
if value == nil {
var zero T
return zero
}
from Miquella (thanks for the insights; I learned something about the usage of ~
, too) made me realize that I don't actually need to specify a specific type once I move the *
onto the parameter type, so this is what I ended up with:
func valueOrNil[T any](value *T) any {
if value == nil {
return nil
}
return *value
}
我正在尝试使用 Go 泛型编写一个函数来减少我们代码中的一些样板 if/else 块。我想出了 something that works for a single type parameter 如下:
func valueOrNil[T *int](value T) any {
if value == nil {
return nil
}
return *value
}
虽然这工作正常,但它并不是很有用,因为它只允许 *int
,而且我希望这段代码适用于任何原始类型。我试图扩展它以支持第二种类型,as follows:
func valueOrNil[T *int | *uint](value T) any {
if value == nil {
return nil
}
return *value
}
但是,此变体因编译器错误而失败:
invalid operation: pointers of value (variable of type T constrained by *int|*uint) must have identical base types
任何人都可以发现我在这里做错了什么,或者像这样的东西只是“不受支持”吗?
问题似乎在于您试图通过 指向类型的指针 而不是 类型本身 来实现通用。如果我们将指针移动到参数本身而不是类型参数上,它就可以工作。
解释如下,但这里是工作代码:
func valueOrNil[T ~int | ~uint](value *T) T {
if value == nil {
var zero T
return zero
}
return *value
}
所以不是这个(这是行不通的):
func valueOrNil[T *int | *uint](value T) any
你可以这样做:
func valueOrNil[T int | uint](value *T) any
但是,您可能希望更进一步并处理基础类型:
func valueOrNil[T ~int | ~uint](value *T) any
这将允许自定义类型与函数一起使用:
type Thing int
var thing Thing
println(valueOrNil(thing))
您可能要考虑的另一个方面是 return 类型的通用性。您可以使用相同的 T
参数。
例如:
func valueOrNil([T ~int | ~uint](value *T) T
但这意味着您需要更改部分实现。而不是这个:
if value == nil {
return nil
}
你可以这样做:
if value == nil {
var zero T
return zero
}
~
, too) made me realize that I don't actually need to specify a specific type once I move the *
onto the parameter type, so this is what I ended up with:
func valueOrNil[T any](value *T) any {
if value == nil {
return nil
}
return *value
}