Golang 泛型应用

Jackey Golang 822 次浏览 , 没有评论

声明一个泛型函数

package main

import "fmt"

func printSlice[T any](s []T){
    for _,v := range s{
        fmt.Printf("%v\n",v)
    }
}


func main(){
    printSlice[int]([]int{66,77,88,99,100})
    printSlice[float64]([]float64{1.1,2.2,5.5})
    printSlice[string]([]string{"烤鸡","烤鸭","烤鱼","烤面筋"})

    //省略显示类型
    printSlice([]int64{55,44,33,22,11})
}

[T any]参数的类型,意思是该函数支持任何T类型;

多个泛型参数语法:

[T, M any]
[T any, M any]
[T any, M comparable]

在调用这个泛型函数的时候,可以显示指定类型参数,

如: printSlice[int]([]int{66,77,88,99,100})

也可以省略显示类型

比如 printSlice([]int64(55,44,33,22,11))

声明一个泛型切片

带有类型参数的类型被叫做泛型类型。下面定义一个底层类型为切片类型的新类型 vector。它是可以存储任何类型的的切片。要使用泛型类型,要先对其进行实例化,就是给类型参数指定一个实参。

package main
import "fmt"

type vector[T any][]T

func printSlice[T any](s []T){
    for _,v := range s{
        fmt.Printf("%v",v)
    }
}

func main(){
    v:=vector[int]{58,1881}
    printSlice(v)
    v2:=vector[string]{"烤鸡","烤鸭","烤鱼","烤面筋"}
    printSlice(v2)
}

声明一个泛型map

package main
import "fmt"

type M[K string, V any] map[K]V   //这里的K不支持any ,由于底层map不支持,所以使用string

func main() {
    m1 := M[string, int]{"key": 1}
    m1["key"] = 2

    m2 := M[string, string]{"key": "value"}
    m2["key"] = "new value"
    fmt.Println(m1, m2)
}

声明一个泛型通道

package main

import "fmt"

type C[T any] chan T

func main() {
    c1 := make(C[int], 10)
    c1 <- 1
    c1 <- 2

    c2 := make(C[string], 10)
    c2 <- "hello"
    c2 <- "world"

    fmt.Println(<-c1, <-c2)
}

泛型约束

使用interface中规定的类型约束泛型函数的参数

package main

import "fmt"

type NumStr interface {
    Num | Str
}
type Num interface {
    ~int | ~int8 | ~int16| ~int32| ~int64| ~uint| ~ uint8| ~ uint16| ~ uint32| ~uint64| ~ uintptr| ~ float32| ~ float64| ~ complex64| ~ complex128
}
type Str interface {
    string
}

func add[T NumStr](a,b T) T {
    return a + b
}

func main(){
    fmt.Println(add(3,4))
    fmt.Println(add("hello","world"))
}

上面的 NumStr,新增了类型列表表达式,它是对类型参数进行约束。

使用 | 表示取并集

如果传入参数不在集合限制范围内,就会报错。

使用interface中规定的方法来约束泛型的参数

package main

import (
    "fmt"
    "strconv"
)

type Price int

func (i Price) String() string {
    return strconv.Itoa(int(i))
}

type Price2 string

func (i Price2) String() string {
    return string(i)
}

type ShowPrice interface {
    String() string
    ~int | ~string
}

func ShowPriceList[T ShowPrice](s []T) (ret []string) {
    for _, v := range s {
        ret = append(ret, v.String())
    }
    return
}

func main() {
    fmt.Println(ShowPriceList([]Price{1, 2}))
    fmt.Println(ShowPriceList([]Price2{"a", "b"}))
}

使用interface中规定的方法和类型来双重约束泛型的参数

package main

import (
    "fmt"
    "strconv"
)

type Price int

type ShowPrice interface {
    String() string
    int | string
}

func (i Price) String() string {
    return strconv.Itoa(int(i))
}

func ShowPriceList[T ShowPrice](s []T) (ret []string) {
    for _, v := range s {
        ret = append(ret, v.String())
    }
    return
}

func main() {
    fmt.Println(ShowPriceList([]Price{1, 2}))
}

//传入浮点参数,就会因为不是约束类型而报错

使用泛型自带comparable约束,判断比较

package main

import (
    "fmt"
)

func findFunc[T comparable](a []T, v T) int {
    for i, e := range a {
        if e == v {
            return i
        }
    }
    return -1
}

func main() {
    fmt.Println(findFunc([]int{1, 2, 3, 4, 5, 6}, 5))
    fmt.Println(findFunc([]string{"烤鸡", "烤鸭", "烤鱼", "烤面筋"}, "烤面筋"))
}

comparable 的约束类型支持整数 和字符,自定义结构体,也可以嵌套在自定义约束中

type ShowPrice interface {	
    int | string | comparable 
}

参考文章:http://www.golang.ren/article/193584

发表评论

您的电子邮箱地址不会被公开。

Go