go - 泛型函数级联调用时的泛型类型推断

标签 go

在构建(我的第一个)泛型重型库时,我遇到了泛型类型检查实现的一些明显限制 - 更可能是我缺乏知识。

有什么想法可以让下面的东西发挥作用吗?

package main

import (
    "fmt"
    "reflect"
)

type Number interface {
    int | float32
}

type MultiDimensionSlice interface {
    int | float32 | []int | []float32 | [][]int | [][]float32
}

func dimensions[S MultiDimensionSlice](s S) int {
    dims := 0
    t := reflect.TypeOf(s)
    for t.Kind() == reflect.Slice {
        dims += 1
        t = t.Elem()
    }
    return dims
}

func indirection[T Number](v T) int {
    var slice2D [][]T
    return dimensions(slice2D)
}

func main() {
    x := [][]float32{{1}, {2}, {3}}
    fmt.Printf("x=%v, dims=%d\n", x, dimensions(x))
    fmt.Printf("indirection should return 2, got %d\n", indirection(0))
}

编译失败,并显示消息 [][]T does not Implement MultiDimensionSlice ([][]T Missing in int | float32 | []int | []float32 | [][]int | [] []float32)

但在函数 indirection() 中,所有允许的 T 值都将在 dimensions() 中实现。

任何帮助或指示将不胜感激!

( Playground link )

ps.:我的问题比这更复杂一点,但问题是一个通用函数(本例中的indirection())无法调用另一个(此处的Dimensions())因为(显然)Go编译器无法解析类型参数约束(信息在编译时就存在......)。

最佳答案

正如评论中提到的,go 在泛型方面有一些限制。您可以通过解决方法来实现您的要求。

首先,您需要更改您定义的接口(interface)。 (也使其通用)

type Number interface {
    int | float32
}

type MultiDimensionSlice[T Number] interface {
    Number | []T | [][]T
}

然后我们需要更改dimension方法类型参数。如果 go 让我们定义这样的 dimensions 方法,那就更清晰了

func  dimensions[S Number](s MultiDimensionSlice[S]) int {

但我们能做的就是:

func dimensions[S Number, K MultiDimensionSlice[S]](s K) int {
    dims := 0
    t := reflect.TypeOf(s)
    for t.Kind() == reflect.Slice {
        dims += 1
        t = t.Elem()
    }
    return dims
}

然后我们需要更改调用dimensions方法的方式。我们需要提供一个额外的类型参数,以便可以推断类型参数 S

func indirection[T Number](v T) int {
    var slice2D [][]T
    return dimensions[T](slice2D)
}

func main() {
    x := [][]float32{{1}, {2}, {3}}
    fmt.Printf("x=%v, dims=%d\n", x, dimensions[float32](x))
    fmt.Printf("indirection should return 2, got %d\n", indirection(0))
}

Playground

关于go - 泛型函数级联调用时的泛型类型推断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73591149/

相关文章:

go - 使用 Golang 时对深度优先搜索结果感到困惑

unit-testing - Golang 单元测试中的 stub 方法

golang语法错误: unexpected in struct

go - 反射设置作为 interface{} 传入的结构体字段

go - 防止Golang后台进程过度使用CPU

python - 为什么我的 Go 程序在以下场景中的性能比预期差很多?

for-loop - 当您使用范围 channel 中断for语句时会发生什么

pointers - golang函数返回接口(interface)指针

csv - Golang,写入csv文件结果文件有时为空

go - Go Web 服务器在哪里查找文件