ToB企服应用市场:ToB评测及商务社交产业平台

标题: golang 基础 泛型编程 [打印本页]

作者: 耶耶耶耶耶    时间: 2024-7-23 08:48
标题: golang 基础 泛型编程
(一) 示例1
  1. package _case
  2. import "fmt"
  3. // 定义用户类型的结构体
  4. type user struct {
  5.         ID   int64
  6.         Name string
  7.         Age  uint8
  8. }
  9. // 定义地址类型的结构体
  10. type address struct {
  11.         ID       int
  12.         Province string
  13.         City     string
  14. }
  15. // 集合转列表函数,接受一个 map,返回一个切片
  16. func mapToList[k comparable, T any](mp map[k]T) []T {
  17.         // 创建切片,长度与 map 的长度相同
  18.         list := make([]T, len(mp))
  19.         var i int
  20.         for _, data := range mp {
  21.                 list[i] = data
  22.                 i++
  23.         }
  24.         return list
  25. }
  26. // 打印通道内容的函数,接受一个通道并打印通道中的每一个数据
  27. func myPrintln[T any](ch chan T) {
  28.         for data := range ch {
  29.                 fmt.Println(data)
  30.         }
  31. }
  32. // 主函数,执行类型转换和打印
  33. func TTypeCase() {
  34.         // 创建一个用户类型的 map
  35.         userMp := make(map[int64]user, 0)
  36.         // 向 map 中添加用户数据
  37.         userMp[1] = user{ID: 1, Name: "heheda", Age: 18}
  38.         userMp[2] = user{ID: 2, Name: "Jerry", Age: 20}
  39.         userMp[3] = user{ID: 3, Name: "Tom", Age: 22}
  40.         // 将用户 map 转换为用户列表
  41.         userList := mapToList[int64, user](userMp)
  42.         // 创建用户类型的通道,并启动 goroutine 打印通道数据
  43.         ch := make(chan user)
  44.         go myPrintln(ch)
  45.         // 将用户列表中的数据发送到通道
  46.         for _, u := range userList {
  47.                 ch <- u
  48.         }
  49.         close(ch)
  50.         // 创建一个地址类型的 map
  51.         addrMp := make(map[int64]address, 0)
  52.         // 向 map 中添加地址数据
  53.         addrMp[1] = address{ID: 1, Province: "湖南", City: "长沙"}
  54.         addrMp[2] = address{ID: 2, Province: "广东", City: "揭阳"}
  55.         // 将地址 map 转换为地址列表
  56.         addrList := mapToList[int64, address](addrMp)
  57.         // 创建地址类型的通道,并启动 goroutine 打印通道数据
  58.         ch1 := make(chan address)
  59.         go myPrintln(ch1)
  60.         // 将地址列表中的数据发送到通道
  61.         for _, addr := range addrList {
  62.                 ch1 <- addr
  63.         }
  64.         close(ch1)
  65. }
  66. // 泛型切片的定义
  67. type List[T any] []T
  68. // 泛型 map 的定义
  69. // 声明两个泛型,分别为 k 、 v
  70. type MapT[k comparable, v any] map[k]v
  71. // 泛型通道的定义
  72. type Chan[T any] chan T
  73. func TTypeCase1() {
  74.         // map[int64]user -> MapT[int64, user]
  75.         userMp := make(MapT[int64, user], 0)
  76.         userMp[1] = user{ID: 1, Name: "heheda", Age: 18}
  77.         userMp[2] = user{ID: 2, Name: "Jerry", Age: 20}
  78.         userMp[3] = user{ID: 3, Name: "Tom", Age: 22}
  79.         var userList List[user]
  80.         userList = mapToList[int64, user](userMp)
  81.         ch := make(Chan[user])
  82.         go myPrintln(ch)
  83.         for _, u := range userList {
  84.                 ch <- u
  85.         }
  86.         close(ch)
  87.         // map[int64]address -> MapT[int64, address]
  88.         addrMp := make(MapT[int64, address], 0)
  89.         addrMp[1] = address{ID: 1, Province: "湖南", City: "长沙"}
  90.         addrMp[2] = address{ID: 2, Province: "广东", City: "揭阳"}
  91.         var addrList List[address]
  92.         addrList = mapToList[int64, address](addrMp)
  93.         ch1 := make(Chan[address])
  94.         go myPrintln(ch1)
  95.         for _, addr := range addrList {
  96.                 ch1 <- addr
  97.         }
  98.         close(ch1)
  99. }
复制代码

这段代码展示了如何使用 Go 语言中的泛型、结构体和通道举行数据处理和打印。以下是对代码各部分的解释:
1.包和导入
  1. package _case
  2. import "fmt"
复制代码

 2.结构体定义

 3.泛型函数
  1. func mapToList[k comparable, T any](mp map[k]T) []T {
  2.     list := make([]T, len(mp))
  3.     var i int
  4.     for _, data := range mp {
  5.         list[i] = data
  6.         i++
  7.     }
  8.     return list
  9. }
复制代码

4.打印通道内容的泛型函数
  1. func myPrintln[T any](ch chan T) {
  2.     for data := range ch {
  3.         fmt.Println(data)
  4.     }
  5. }
复制代码

5.主函数 TTypeCase
  1. func TTypeCase() {
  2.     userMp := make(map[int64]user, 0)
  3.     userMp[1] = user{ID: 1, Name: "heheda", Age: 18}
  4.     userMp[2] = user{ID: 2, Name: "Jerry", Age: 20}
  5.     userMp[3] = user{ID: 3, Name: "Tom", Age: 22}
  6.     userList := mapToList[int64, user](userMp)
  7.    
  8.     ch := make(chan user)
  9.     go myPrintln(ch)
  10.     for _, u := range userList {
  11.         ch <- u
  12.     }
  13.     close(ch)
  14.    
  15.     addrMp := make(map[int64]address, 0)
  16.     addrMp[1] = address{ID: 1, Province: "湖南", City: "长沙"}
  17.     addrMp[2] = address{ID: 2, Province: "广东", City: "揭阳"}
  18.     addrList := mapToList[int64, address](addrMp)
  19.    
  20.     ch1 := make(chan address)
  21.     go myPrintln(ch1)
  22.     for _, addr := range addrList {
  23.         ch1 <- addr
  24.     }
  25.     close(ch1)
  26. }
复制代码

 6.型范例

  1. type List[T any] []T
  2. type MapT[k comparable, v any] map[k]v
  3. type Chan[T any] chan T
复制代码
7.另一主函数 TTypeCase1
  1. func TTypeCase1() {
  2.     // map[int64]user -> MapT[int64, user]
  3.     userMp := make(MapT[int64, user], 0)
  4.     userMp[1] = user{ID: 1, Name: "heheda", Age: 18}
  5.     userMp[2] = user{ID: 2, Name: "Jerry", Age: 20}
  6.     userMp[3] = user{ID: 3, Name: "Tom", Age: 22}
  7.    
  8.     var userList List[user]
  9.     userList = mapToList[int64, user](userMp)
  10.    
  11.     ch := make(Chan[user])
  12.     go myPrintln(ch)
  13.     for _, u := range userList {
  14.         ch <- u
  15.     }
  16.     close(ch)
  17.    
  18.     // map[int64]address -> MapT[int64, address]
  19.     addrMp := make(MapT[int64, address], 0)
  20.     addrMp[1] = address{ID: 1, Province: "湖南", City: "长沙"}
  21.     addrMp[2] = address{ID: 2, Province: "广东", City: "揭阳"}
  22.    
  23.     var addrList List[address]
  24.     addrList = mapToList[int64, address](addrMp)
  25.    
  26.     ch1 := make(Chan[address])
  27.     go myPrintln(ch1)
  28.     for _, addr := range addrList {
  29.         ch1 <- addr
  30.     }
  31.     close(ch1)
  32. }
复制代码

相关知识点


可以实验运行和修改代码,进一步理解这些概念。
(二) 示例2
  1. package _case
  2. import "fmt"// 定义接口 ToString,有一个 String() 方法type ToString interface {        String() string}// user 结构体实现 ToString 接口func (u user) String() string {        return fmt.Sprintf("ID: %d,Name: %s,Age: %d", u.ID, u.Name, u.Age)}// address 结构体实现 ToString 接口func (addr address) String() string {        return fmt.Sprintf("ID: %d,Province: %s,City: %s", addr.ID, addr.Province, addr.City)}// 定义泛型接口 GetKey,要求实现 Get() 方法返回范例 Ttype GetKey[T comparable] interface {
  3.         any        Get() T}// user 结构体实现 GetKey 接口,Get() 返回 IDfunc (u user) Get() int64 {        return u.ID}// address 结构体实现 GetKey 接口,Get() 返回 IDfunc (addr address) Get() int {        return addr.ID}// 泛型函数 listToMap,将列表转换为 mapfunc listToMap[k comparable, T GetKey[k]](list []T) map[k]T {        mp := make(map[k]T, len(list)) // 创建 map,长度为列表长度        for _, data := range list {                mp[data.Get()] = data // 使用 Get() 方法获取键        }        return mp}// 主函数,演示列表转 map 的操纵func InterfaceCase() {        // 创建 user 列表,元素实现了 GetKey[int64] 接口        userList := []GetKey[int64]{                user{ID: 1, Name: "张三", Age: 18},                user{ID: 2, Name: "李四", Age: 19},        }        // 创建 address 列表,元素实现了 GetKey[int] 接口        addrList := []GetKey[int]{                address{ID: 1, Province: "广东", City: "揭阳"},                address{ID: 2, Province: "湖南", City: "长沙"},        }        // 将 user 列表转换为 map,并打印效果        userMp := listToMap[int64, GetKey[int64]](userList)        fmt.Println(userMp)        // 将 address 列表转换为 map,并打印效果        addrMp := listToMap[int, GetKey[int]](addrList)        fmt.Println(addrMp)}
复制代码

 1.包和导入
  1. package _case
  2. import "fmt"
复制代码
 导入 fmt 包用于格式化输入输出。
2.定义基本接口
  1. type ToString interface {
  2.     String() string
  3. }
复制代码
3.实现 ToString 接口
  1. func (u user) String() string {
  2.     return fmt.Sprintf("ID: %d,Name: %s,Age: %d", u.ID, u.Name, u.Age)
  3. }
  4. func (addr address) String() string {
  5.     return fmt.Sprintf("ID: %d,Province: %s,City: %s", addr.ID, addr.Province, addr.City)
  6. }
复制代码

 4.定义泛型接口
  1. type GetKey[T comparable] interface {
  2.     any
  3.     Get() T
  4. }
复制代码
这是一个泛型接口声明。具体来说,GetKey 接口担当一个范例参数 T,这个范例参数必须是一个可比较的范例 (comparable)
(1)定义泛型接口
  1. type GetKey[T comparable] interface {
复制代码

(2)嵌入 any 接口

(3)定义方法
  1. Get() T
复制代码

5.实现 GetKey 接口
  1. func (u user) Get() int64 {
  2.     return u.ID
  3. }
  4. func (addr address) Get() int {
  5.     return addr.ID
  6. }
复制代码

 6.列表转聚集函数
  1. func listToMap[k comparable, T GetKey[k]](list []T) map[k]T {
  2.     mp := make(MapT[k, T], len(list))
  3.     for _, data := range list {
  4.         mp[data.Get()] = data
  5.     }
  6.     return mp
  7. }
复制代码

 7.主函数 InterfaceCase
  1. func InterfaceCase() {
  2.     userList := []GetKey[int64]{
  3.         user{ID: 1, Name: "张三", Age: 18},
  4.         user{ID: 2, Name: "李四", Age: 19},
  5.     }
  6.     addrList := []GetKey[int]{
  7.         address{ID: 1, Province: "广东", City: "揭阳"},
  8.         address{ID: 2, Province: "湖南", City: "长沙"},
  9.     }
  10.     userMp := listToMap[int64, GetKey[int64]](userList)
  11.     fmt.Println(userMp)
  12.     addrMp := listToMap[int, GetKey[int]](addrList)
  13.     fmt.Println(addrMp)
  14. }
复制代码

>>分解解读
(1)创建 user 结构体实例
  1. user{ID: 1, Name: "张三", Age: 18},
  2. user{ID: 2, Name: "李四", Age: 19},
复制代码

 (2)实现 GetKey[int64] 接口

 (3)创建并初始化切片
  1. userList := []GetKey[int64]{
  2.     user{ID: 1, Name: "张三", Age: 18},
  3.     user{ID: 2, Name: "李四", Age: 19},
  4. }
复制代码

(4)作用

总结


相关知识点
接口 

泛型 

结构体

map

导入包

(三)  示例3
  1. package _receiver
  2. import "fmt"
  3. // 定义一个泛型结构体 MyStruct
  4. // 该结构体接受一个类型参数 T,T 只能是 *int 或 *string
  5. type MyStruct[T interface{ *int | *string }] struct {
  6.         Name string // 结构体的名字字段
  7.         Data T      // 结构体的数据字段,类型为 T
  8. }
  9. // 定义 MyStruct 结构体的泛型方法接收器
  10. // GetData 返回结构体中的 Data 字段
  11. func (myStruct MyStruct[T]) GetData() T {
  12.         return myStruct.Data
  13. }
  14. // 主函数,演示 MyStruct 结构体和其方法的使用
  15. func ReceiverCase() {
  16.         // 定义一个整型变量,并创建 MyStruct 实例
  17.         data := 18
  18.         myStruct := MyStruct[*int]{
  19.                 Name: "heheda",
  20.                 Data: &data, // 将整型变量的指针分配给 Data 字段
  21.         }
  22.         // 调用 GetData 方法获取 Data 字段的值并打印
  23.         data1 := myStruct.GetData()
  24.         fmt.Println(*data1) // 解引用指针打印值,输出 18
  25.         // 定义一个字符串变量,并创建 MyStruct 实例
  26.         str := "abcdefg"
  27.         myStruct1 := MyStruct[*string]{
  28.                 Name: "heheda",
  29.                 Data: &str, // 将字符串变量的指针分配给 Data 字段
  30.         }
  31.         // 调用 GetData 方法获取 Data 字段的值并打印
  32.         str1 := myStruct1.GetData()
  33.         fmt.Println(*str1) // 解引用指针打印值,输出 "abcdefg"
  34. }
复制代码
这段代码展示了如安在 Go 语言中使用泛型定义结构体和方法接收器,以下是对代码各部分的解释:
1.包和导入
  1. package _receiver
  2. import "fmt"
复制代码
导入 fmt 包用于格式化输入输出
2.定义泛型结构体
  1. type MyStruct[T interface{ *int | *string }] struct {
  2.     Name string
  3.     Data T
  4. }
复制代码

 3.定义泛型方法接收器
  1. func (myStruct MyStruct[T]) GetData() T {
  2.     return myStruct.Data
  3. }
复制代码

 4.主函数 ReceiverCase
  1. func ReceiverCase() {
  2.     data := 18
  3.     myStruct := MyStruct[*int]{
  4.         Name: "heheda",
  5.         Data: &data,
  6.     }
  7.     data1 := myStruct.GetData()
  8.     fmt.Println(*data1)
  9.     str := "abcdefg"
  10.     myStruct1 := MyStruct[*string]{
  11.         Name: "heheda",
  12.         Data: &str,
  13.     }
  14.     str1 := myStruct1.GetData()
  15.     fmt.Println(*str1)
  16. }
复制代码

相关知识点

(1)泛型

(2)结构体

(3)方法接收器

(4)指针

(5)导入包

可以实验运行和修改代码,进一步理解这些概念。
main.go
  1. package main
  2. import (
  3.         "context"
  4.         _case "gomod/genetic-T/case"
  5.         "os"
  6.         "os/signal"
  7. )
  8. func main() {
  9.         _case.TTypeCase()
  10.         _case.TTypeCase1()
  11.         _case.InterfaceCase()
  12.         _receiver.ReceiverCase()
  13.         ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)
  14.         defer stop()
  15.         <-ctx.Done()
  16. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4