Go语言入门11(泛型)

打印 上一主题 下一主题

主题 945|帖子 945|积分 2835

泛型

问题解决

一个计算sum的函数
  1. func sum(slice []int) int {
  2.         var res int
  3.         for _, value := range slice {
  4.                 res += value
  5.         }
  6.         return res
  7. }
复制代码
​        如果需要提供对int,float64,string三种数据类型的求sum函数,那么不使用泛型的情况下就需要单独写三个函数,此时就需要使用泛型这种概念,来避免重复代码出现
  1. // 这里中括号中括起来的就是泛型的定义,将这三种数据类型定义为T泛型,同时使用T泛型来定义入参和返回值的数据类型
  2. func Sum[T int | float64 | string](slice []T) T {
  3.         var res T
  4.         for _, value := range slice {
  5.                 res += value
  6.         }
  7.         return res
  8. }
  9. // 这样在调用函数的时候,只需要知道具体T泛型对应的是哪种数据类型,就可以确定入参和返回值的数据类型了
  10. func main() {
  11.         slice01 := []int{1, 2, 3}
  12.         fmt.Printf("%d\n", Sum(slice01)) // 6
  13.         slice02 := []float64{1.2, 2.2, 3.2}
  14.         fmt.Printf("%.2f\n", Sum(slice02))  // 6.60
  15.         slice03 := []string{"Hello", " ", "world!"}
  16.         fmt.Printf("%s\n", Sum(slice03)) // Hello world!
  17. }
复制代码
泛型的使用


  • 在函数传参中使用泛型
​        同上一个例子相同,在函数声明中定义泛型,然后将他利用于入参,返回值,以及函数的内部定义
  1. func Demo01[T int | string](input T) {
  2.         fmt.Println(reflect.TypeOf(input))
  3. }
  4. func main() {
  5.     // 通过传参来判断泛型T具体的数据类型
  6.     // T:string
  7.     Demo01("我是string类型") // string
  8.     // T:int
  9.     Demo01(123) // int
  10. }
复制代码

  • 泛型结构体
​        同样,泛型也适用于结构体,在结构体声明时定义泛型,既可以在结构体内部使用泛型来声明值的类型
  1. // 使用泛型T来让生产日期的数据类型多样化,可以是int也可以是string
  2. type robots[T int | string] struct {
  3.         name             string
  4.         yearOfProduction T
  5. }
  6. func Demo03() {
  7.     // 使用带有泛型的结构体实例化对象的时候,要确定泛型T的具体类型
  8.     // T:string
  9.         myRobot01 := robots[string]{"robot01", "2023"}
  10.     // T:int
  11.         myRobot02 := robots[int]{"robot02", 2023}
  12.         fmt.Printf("%T : %T\n", myRobot01.name, myRobot01.yearOfProduction) // string : string
  13.         fmt.Println(myRobot01.name, " : ", myRobot01.yearOfProduction) // robot01  :  2023
  14.         fmt.Printf("%T : %T\n", myRobot02.name, myRobot02.yearOfProduction) // string : int
  15.         fmt.Println(myRobot02.name, " : ", myRobot02.yearOfProduction) // robot02  :  2023
  16. }
复制代码

  • 给泛型添加方法
  1. // 先声明带有泛型的切片slice[]
  2. type Slice[T int | string | float64] []T
  3. // 然后给这个切片添加方法
  4. func (mySlice Slice[T]) Demo04() T {
  5.         var res T
  6.         for _, t := range mySlice {
  7.                 res += t
  8.         }
  9.         return res
  10. }
  11. func main() {
  12.     // 再使用切片实例化对象时同样需要先确定泛型T的具体类型
  13.         var slice01 Slice[int] = []int{1, 2, 3}
  14.     // 直接使用里面的方法
  15.         fmt.Printf("%d\n", slice01.Demo04())
  16.         var slice02 Slice[float64] = []float64{1.2, 2.2, 3.2}
  17.         fmt.Printf("%.2f\n", slice02.Demo04())
  18.         var slice03 Slice[string] = []string{"Hello", " ", "world!"}
  19.         fmt.Printf("%s\n", slice03.Demo04())
  20. }
复制代码

  • 自定义泛型类型
​        如果类型太多了怎么办呢?这时候我们就可以自定义泛型类型
  1. // 声明方式类似接口
  2. type MyInt interface{
  3.     int | int8 | int16 | int32 | int64
  4. }
  5. // T的类型为声明的MyInt
  6. func GetMax[T MyInt](a,b T) T {
  7.     if a > b {
  8.         return a
  9.     }
  10.     return b
  11. }
复制代码
特殊的泛型

go里内置了两个泛型类型:any和comparable
泛型类型作用any表示go里面所有的内置基本类型,等价于interface{}comparable表示go里面所有内置的可以进行比较的类型总结

​        总而言之,这些初级用法,可以使代码变得非常的简洁,降低代码重复,在下面情景的时候非常适合使用泛型:当你需要针对不同类型书写同样的逻辑,使用泛型来简化代码是最好的

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

慢吞云雾缓吐愁

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表