实验Go泛型新特性

实验Go 泛型新特性:

一.先决条件: 运行以下两行命令去下载支持运行泛型的go编译环境。

go get golang.org/dl/go1.18beta1@latest
// 下载go1.18beta1 可执行文件到go配置的bin目录下
go1.18beta1 download
// 检查是否下载成功
go1.18beta1 version
//测试的代码要用go1.18beta1 来run。

二. 不用泛型实现把一个map里的所有value求和,且这个value可能是int64或者float64。
代码示例:

package main


/**
   以下示例显示了用两个不同的Sum类型方法处理累加
 */


import "fmt"


// SumInts 累加map里的int64类型的value
func SumInts(m map[string]int64) int64 {
   var s int64
   for _, v := range m {
      s += v
   }
   return s
}

// SumFloats 累加map里的float64类型的value
func SumFloats(m map[string]float64) float64 {
   var s float64
   for _, v := range m {
      s += v
   }
   return s
}

func main() {
   // 初始化测试int64类型累加的map
   ints := map[string]int64{
      "first": 34,
      "second": 12,
   }

   // 初始化测试float64类型累加的map
   floats := map[string]float64{
      "first": 35.98,
      "second": 26.99,
   }

   fmt.Printf("Non-Generic Sums: %v and %v\n",
      SumInts(ints),
      SumFloats(floats))

}

NOTE: 使用刚下载命令或者直接go run都可以:

三.目标: 使用泛型函数(generic function)去处理多种类型。
以下示例用一个可以同时接收interger 和 float的泛型map,替换掉上述使用两个方法去处理sumxxx功能。
要实现这个目标,需要明确以下步骤:

  • 定义泛型类型去同时支持多种类型。
  • 编写函数时,除了原来的函数定义外,还需要定义 type parameters 泛型的类型,这个定义可以让方法使用泛型的特性,使它可以同时接收不同类型的参数。
  • 类型参数(type parameters)可以限制一组类型,但是在编译时,只能代表一种类型,这个类型是调用这个方法传入的类型,如果传入的类型不符合类型参数限制的,就无法编译通过。

类型参数type parameters怎么定义?
func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V

当我们定义的函数需要使用泛型时,在函数名和实际传参列表之间需要用[ ] 给出用到的类型参数的定义。 如果支持多种类型,用 | 隔开。

代码示例:

package main


import "fmt"


func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V {
   var result V
   for _,v := range m {
      result += v
   }

   return result
}

func main() {

   // Initialize a map for the integer values
   ints := map[string]int64{
      "first": 34,
      "second": 12,
   }

   // Initialize a map for the float values
   floats := map[string]float64{
      "first": 35.98,
      "second": 26.99,
   }

   fmt.Printf("Generic Sums: %v and %v\n",
      SumIntsOrFloats[string, int64](ints),
      SumIntsOrFloats[string, float64](floats))
}
Note: 如果代码是在goland里编写的,要注意goland的编译环境会提示报错,这里运行要在commandline里使用   go1.18beta1 run main.go  来运行。
   从示例中可以看到,不仅函数定义要添加[K Ktype, V Vtype]的限制,在调用方法时,也要给K V限制传入的类型。
实际上,这里在调用方法时不传类型声明也可以,编译器会有类型推断的功能,把fmt改为一下的方式调用同样可以。
fmt.Printf("Generic Sums: %v and %v\n",
   SumIntsOrFloats(ints),
   SumIntsOrFloats(floats))

四. 泛型参数使用接口声明:
这里的V的类型可以是多种类型的参数,我们可能需要支持不同类型的sum操作,每个方法都这样定义很不方便,以下使用接口声明泛型参数支持的类型的示例:

type Number interface {
   int64 | float64
}

定义一个type Number 的接口类型,把所有支持的参数都在这里定义。

函数的声明修改:

func SumNumbers[K comparable, V Number](m map[K]V) V {
   var result V
   for _,v := range m {
      result += v
      }
      
   return result
   }

这里V的类型改成了接口的类型。

调用方法打印同样没有问题:

fmt.Printf("Generic Sums with Constraint: %v and %v\n",
   SumNumbers(ints),
   SumNumbers(floats))

完整的代码示例:
https://github.com/hinss/golearn/tree/master/generic_test

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值