golang - 泛型

2022-03-22  本文已影响0人  husky_1
1. 申明一个泛型函数
package main

import "fmt"

//约定了T为any类型(any 底层就是空接口), 形参s是元素为T类型的切片, 等价于[]interface{}
func printslice[T any](s []T){
    for _,v := range s{
        fmt.Printf("%v\n",v)
    }
}


func main(){
    printslice[int]([]int{1,2,3,4})
    printslice[float64]([]float64{1.1,2.2,3.3
    printslice[string]([]string{"aasdf","asdasdad"}

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

}

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

多个泛型参数语法:

[T, M any]
[T any, M any]
[T any, M comparable]
2. 申明泛型切片

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

// 约定参数类型为any 
type slice[T any] []T
package main

import "fmt"

type slice[T any] []T

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

func main() {
    // 初始化一个泛型类型,对应类型为int
    s1 := slice[int]{1, 2, 3}
    printslice(s1)
    // 初始化一个泛型类型,对应类型为string
    s2 := slice[string]{"123", "4r11"}
    printslice(s2)
}
3. 申明map 类型
// 申明一个k 为可比较类型,v 为any 类型的泛型map,在go 中k的值必须为可比较的,否则会报错 Invalid map key type: comparison operators == and != must be fully defined for the key type
type Map[K comparable,V any] map[K]V
package main
import "fmt"

type Map[K comparable, V any] map[K]V  

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

    m2 := Map[string, string]{"key": "value"}
    m2["key"] = "new value"
    fmt.Println(m1, m2)
}
4. 申明通道类型
type Chan[T any]  chan T
package main

import "fmt"

type Chan[T any] chan T

func main() {
    c1 := make(Chan[int], 10)
    c1 <- 1
    
    c2 := make(Chan[string], 10)
    c2 <- "hello"

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

5. 泛型约束
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
}

type myInt int

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

func main(){
   // 等价于fmt.Println(add[int](3, 111))
   fmt.Println(add(3, 111))
   // 等价于fmt.Println(add[string]("hello", "world"))
   fmt.Println(add("hello", "world"))
   fmt.Println(myInt(1), 2) // myInt 底层也是int 类型,所以也是NumStr类型,可以使用
}

上面的 NumStr,新增了类型列表表达式,它是对类型参数进行约束。
使用 | 表示取并集
~int 指的是底层是int 类型的数据类型,例如自定义的myInt 类型
如果传入参数不在集合限制范围内,就会报错

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
}

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"}))
}
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
    // 底层是string和int类型
    ~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"}))
}
6. 自带的类型约束 any 和 comparable

any 底层就是一个空接口
any

// any is an alias for interface{} and is equivalent to interface{} in all ways.
type any = interface{}

comparable
可比较的类型包括了booleans, numbers, strings, pointers, channels, arrays , 所有的字段都是可比较的结构体。
该接口只是用于作为泛型约束的使用

// comparable is an interface that is implemented by all comparable types
// (booleans, numbers, strings, pointers, channels, arrays of comparable types,
// structs whose fields are all comparable types).
// The comparable interface may only be used as a type parameter constraint,
// not as the type of a variable.
type comparable interface{ comparable }

comparable也可以嵌套在自定义约束中

type ShowPrice interface {  
    int | string | 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{"烤鸡", "烤鸭", "烤鱼", "烤面筋"}, "烤面筋"))
}

6. 注意
7. 参考:https://www.bilibili.com/video/BV1PY41137Vn?p=9&spm_id_from=pageDriver
上一篇下一篇

猜你喜欢

热点阅读