IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> golang泛型 -> 正文阅读

[游戏开发]golang泛型

泛型

go1.18版本开始支持
在函数上使用[T 支持的类型] 表示泛型,比如

func AddSum[T int|float64](params ...T)(sum T){
  // 一些操作
  return sum
}

自带泛型:

  1. any 表示任何类型,即interface
  2. comparable 表示可以被比较的类型
    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.

就个人而言,泛型的使用倒是可以解决不同类型的相同函数的编写,但是对于其其它妙用还不太明确,需要慢慢体会

在函数上申明多个类型约束


// 1. 泛型的类型限制,在函数上直接申明该函数支持的多个类型
func AddElem[T int | string](params []T) (sum T) {
    for _, elem := range params {
        sum += elem
    }
    return
}

func TestGenerics_AddElem(t *testing.T) {

    // 1. 在函数上声明泛型支持的多个类型
    // 1.1 传入支持的int
    intSum := AddElem([]int{1, 2, 3, 4, 5, 6, 7, 8, 9})
    t.Logf("测试1.1: 类型=%T,val=%+v", intSum, intSum)

    // 1.2 传入支持的string
    strSum := AddElem([]string{"静", "以", "修", "身", ",", "俭", "以", "养", "德"})
    t.Logf("测试1.2: 类型=%T,val=%+v", strSum, strSum)

    // 1.3 传入不支持的类型  ./generics_test.go:29:24: float64 does not implement int|string
    //floatSum := AddElem([]float64{1, 2, 3, 4, 5, 6, 7, 8, 9})
    //t.Logf("测试1.3: 类型=%T,val=%+v", floatSum, floatSum)
}

声明一个约束集合

// 2 泛型的类型限制,声明一个interface,包括所有需要支持的类型
// ~int 表示底层数据是int
type NumStr interface {
    ~int | ~uint | ~float64 | ~string
}

type MyInt int

func AddNumStr[T NumStr](params []T) (sum T) {
    for _, param := range params {
        sum += param
    }
    return
}

func TestGenerics_AddNumStr(t *testing.T) {
    // 2.1 支持的int
    intSum := AddNumStr([]int{1, 2, 3, 4, 5, 6, 7, 8, 9})
    t.Logf("测试2.1: 类型=%T,val=%+v", intSum, intSum)

    // 2.2 传入支持的string
    strSum := AddNumStr([]string{"风", "平", "浪", "静"})
    t.Logf("测试2.2: 类型=%T,val=%+v", strSum, strSum)

    // 2.3 传入自定义int
    myIntSum := AddNumStr([]MyInt{1, 2, 3, 4, 5, 6, 7, 8, 9})
    t.Logf("测试2.3: 类型=%T,val=%+v", myIntSum, myIntSum)
}

泛型切片

// 3. 泛型切片
// any为泛型自带的一种类型,即interface
type Vector[T any] []T
type NumSlice[T int | float64] []T

func AddElem[T int | string](params []T) (sum T) {
    for _, elem := range params {
        sum += elem
    }
    return
}

func TestGenerics_Slice(t *testing.T) {
    // 测试3.1
    v := Vector[string]{"z", "x", "c"}
    t.Logf("测试3.1: 类型=%T,val=%+v", v, v)

    // 测试3.2
    ns := NumSlice[int]{1, 2, 3, 4, 5, 6}
    t.Logf("测试3.2: 类型=%T,val=%+v", ns, ns)

    // 测试3.3
    sum := AddElem(ns)
    t.Logf("测试3.3: 类型=%T,val=%+v", sum, sum)
}

泛型Map

// 4. 泛型map
type M[K string, V any] map[K]V

func TestGenerics_Map(t *testing.T) {
    m := M[string, int]{
        "zx": 123,
        "as": 456,
        "qw": 789,
    }
    t.Logf("测试4.1: 类型=%T,val=%+v", m, m)
}

泛型通道

// 5. 泛型通道
type Ch[T any] chan T

func TestGenerics_Chan(t *testing.T) {
    ch := make(Ch[int], 1)
    ch <- 10

    res := <-ch
    t.Logf("测试5.1: 类型=%T,val=%+v", res, res)
    t.Logf("测试5.2: 类型=%T,val=%+v", ch, ch)
}

方法约束


// 6. 方法约束
type FlyAnimal interface {
    ToString() string
}

// Dragon实现了FlyAnimal
type Dragon int

func (d Dragon) ToString() string {
    return "string_" + strconv.Itoa(int(d))
}

// Tiger没有实现flyAnimal
type Tiger int

func PrintStr[T FlyAnimal](params ...T) {
    for _, param := range params {
        fmt.Println(param.ToString())
    }
}

func TestGenerics_Method_limit(t *testing.T) {
    // 测试6.1 传入实现了方法的类型
    dragon := Dragon(1)
    PrintStr(dragon)

    // 测试6.2 传入未实现对应方法的类型  ./generics_test.go:136:13: Tiger does not implement FlyAnimal (missing ToString method)
    //tiger := Tiger(100)
    //PrintStr(tiger)
}

类型加方法的双重约束


// 7. 类型+方法的约束
type CanSpeak interface {
    ~int | ~int32 | ~int64 | ~float32 | ~float64
    Speak() string
}

type Mouth int32

func (m Mouth) Speak() string {
    return fmt.Sprintf("speak %v", m)
}

type Nose string

func (n Nose) Speak() string {
    return fmt.Sprintf("speak %v", n)
}

type Ear int

func SpeakLoudly[T CanSpeak](params []T) {
    for _, param := range params {
        fmt.Println(param.Speak())
    }
}

func TestGenerics_Type_Method_Limit(t *testing.T) {
    // 7.1 测试类型与方法均符合
    SpeakLoudly([]Mouth{1, 2, 3, 4, 5, 6})

    // 7.2 测试类型符合   ./generics_test.go:172:16: Nose does not implement CanSpeak
    //SpeakLoudly([]Nose{"z", "x", "c"})

    // 7.3 测试方法符合   ./generics_test.go:175:16: Ear does not implement CanSpeak (missing Speak method)
    //SpeakLoudly([]Ear{1, 2, 3, 4, 5, 6})
}

参考

golang泛型介绍

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-06 16:21:40  更:2022-04-06 16:25:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/16 21:09:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码