如何编写一个允许指向多个基元类型的通用 Go 函数?

mpo*_*llo 2 generics go

我正在尝试使用 Go 泛型编写一个函数来减少代码中的一些样板 if/else 块。我想出了一些适用于单个类型参数的方法,如下所示:

func valueOrNil[T *int](value T) any {
    if value == nil {
        return nil
    }
    return *value
}
Run Code Online (Sandbox Code Playgroud)

虽然这工作正常,但它并不是真正有用,因为它只允许*int, 并且我希望此代码可以与任何原始类型一起使用。我尝试扩展它以支持第二种类型,如下所示

func valueOrNil[T *int | *uint](value T) any {
    if value == nil {
        return nil
    }
    return *value
}
Run Code Online (Sandbox Code Playgroud)

但是,此变体失败并出现编译器错误:

invalid operation: pointers of value (variable of type T constrained by *int|*uint) must have identical base types
Run Code Online (Sandbox Code Playgroud)

谁能发现我在这里做错了什么,或者这样的事情只是“不支持”?

Miq*_*lla 5

问题似乎在于您试图通过指向类型的指针而不是类型本身来通用。如果我们将指针移动到参数本身而不是类型参数上,它就可以工作。

解释如下,但这是工作代码:

func valueOrNil[T ~int | ~uint](value *T) T {
    if value == nil {
        var zero T
        return zero
    }
    return *value
}
Run Code Online (Sandbox Code Playgroud)

所以代替这个(这不起作用):

func valueOrNil[T *int | *uint](value T) any
Run Code Online (Sandbox Code Playgroud)

你可以这样做:

func valueOrNil[T int | uint](value *T) any
Run Code Online (Sandbox Code Playgroud)

但是,您可能想更进一步并处理底层类型:

func valueOrNil[T ~int | ~uint](value *T) any
Run Code Online (Sandbox Code Playgroud)

这将允许自定义类型与函数一起使用:

type Thing int

var thing Thing
println(valueOrNil(thing))
Run Code Online (Sandbox Code Playgroud)

您可能需要考虑的另一个方面是返回类型也是通用的。您可以使用相同的T参数来执行此操作。

例如:

func valueOrNil([T ~int | ~uint](value *T) T
Run Code Online (Sandbox Code Playgroud)

但这意味着您需要更改部分实现。而不是这个:

if value == nil {
    return nil
}
Run Code Online (Sandbox Code Playgroud)

你可以这样做:

if value == nil {
    var zero T
    return zero
}
Run Code Online (Sandbox Code Playgroud)