go泛型入门

2023-07-12  本文已影响0人  护念

什么是泛型,简单点说就是,用同一个函数,处理不同的数据类型。

看下面的例子,会有深入的感受

1.用两个不同类型的函数,处理不同的类型

mkdir generics
cd generics
go mod init example/generics # 初始化模块
// mian.go
package main

import "fmt"

func main() {
     // 初始化整数映射
    ints := map[string]int64{
        "first":  34,
        "second": 12,
    }

    // 初始化浮点数映射
    floats := map[string]float64{
        "first":  35.98,
        "second": 26.99,
    }

    fmt.Printf("Non-Generic Sums: %v and %v\n",
        SumInts(ints),
        SumFloats(floats))
}

// int64 求和
func SumInts(m map[string]int64) int64 {
    var s int64
    for _, v := range m {
        s += v
    }
    return s
}

// float64求和
func SumFloats(m map[string]float64) float64 {
    var s float64
    for _, v := range m {
        s += v
    }
    return s
}
dongmingyan@pro ⮀ ~/go_playground/generics ⮀ go run .
Non-Generic Sums: 46 and 62.97

2.引入泛型

在上面我们用了两个不同的函数分别处理int和float类型,实在有点麻烦;这里我们用一个函数实现

// main.go
package main

import "fmt"

func main() {
     // 初始化整数映射
    ints := map[string]int64{
        "first":  34,
        "second": 12,
    }

    // 初始化浮点数映射
    floats := map[string]float64{
        "first":  35.98,
        "second": 26.99,
    }

    fmt.Printf("Non-Generic Sums: %v and %v\n",
        SumIntsOrFloats[string, int64](ints), // 使用时候也多传下类型,如果可以类型推断出来可以省略
        SumIntsOrFloats[string, float64](floats))

        // 和上写法等效
        fmt.Printf("Non-Generic Sums: %v and %v\n",
        SumIntsOrFloats(ints),
        SumIntsOrFloats(floats))
}
// 求和浮点数或整数
// [] 里申明类型
// comparable代表一种可以比较的类型
func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V {
    var sum V

    for _, v := range m {
        sum += v
    }
    return sum
}

运行

dongmingyan@pro ⮀ ~/go_playground/generics ⮀ go run .
Non-Generic Sums: 46 and 62.97
Non-Generic Sums: 46 and 62.97

小结:方式就是在函数开头加上[],设定好支持哪些类型

3.优化-类型约束

上面的写法已经实现了替代两个函数,但是并不简洁,如果有许多个地方都需要用到这种数据类型,我们并没有办法复用;我们可以把这里的类型抽取出来

// main.go
package main

import "fmt"

func main() {
     // 初始化整数映射
    ints := map[string]int64{
        "first":  34,
        "second": 12,
    }

    // 初始化浮点数映射
    floats := map[string]float64{
        "first":  35.98,
        "second": 26.99,
    }

    fmt.Printf("Non-Generic Sums: %v and %v\n",
        SumIntsOrFloats[string, int64](ints), // 使用时候也多传下类型,如果可以类型推断出来可以省略
        SumIntsOrFloats[string, float64](floats))

        // 和上写法等效
        fmt.Printf("Non-Generic Sums: %v and %v\n",
        SumIntsOrFloats(ints),
        SumIntsOrFloats(floats))
}

// 这里申明一种Number类型 可以同时代表int64和float64
type Number interface{
    int64 | float64 // 注意这里是单竖线
}

// 求和浮点数或整数
// [] 里申明类型
// compareable代表一种可以比较的类型 Number复用其中
func SumIntsOrFloats[K comparable, V Number](m map[K]V) V {
    var sum V

    for _, v := range m {
        sum += v
    }
    return sum
}
上一篇下一篇

猜你喜欢

热点阅读