代码之家  ›  专栏  ›  技术社区  ›  mpontillo

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

  •  0
  • mpontillo  · 技术社区  · 3 年前

    我试图使用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
    

    有人能看出我做错了什么吗,或者像这样的事情只是“不受支持”?

    1 回复  |  直到 3 年前
        1
  •  1
  •   Miquella    3 年前

    问题似乎是,你在试图超越常规 指针 与类型而不是 自己打字 .如果我们将指针移动到参数本身而不是类型参数上,它就会工作。

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

    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))
    

    另一个方面,您可能需要考虑的是泛型超过返回类型。你可以用同样的方法 T 参数

    例如:

    func valueOrNil([T ~int | ~uint](value *T) T
    

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

    if value == nil {
        return nil
    }
    

    你可以这样做:

    if value == nil {
        var zero T
        return zero
    }
    
        2
  •  0
  •   mpontillo    3 年前

    这个 answer I accepted 从…起 Miquella (谢谢你的见解;我学到了一些关于 ~ ,也)使我意识到,一旦我移动 * 在参数类型上,所以 this is what I ended up with :

    func valueOrNil[T any](value *T) any {
        if value == nil {
            return nil
        }
        return *value
    }