前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >go1.17 泛型尝鲜

go1.17 泛型尝鲜

作者头像
老麦
发布2022-12-24 09:31:27
1860
发布2022-12-24 09:31:27
举报
文章被收录于专栏:Go与云原生Go与云原生

go1.17 泛型尝鲜

语法格式如下, 需要使用 [T Ttype] 指定约束条件, 例如 [T any] 不做任何约束, [T MyInterface] 满足 MyInterface 的约束

接下来我们将尝试上述提到的内容。

代码语言:javascript
复制
func fname[T Ttype](args []T) T {
	// statement
}

需要注意的是,

  1. 现在泛型在 go1.17 中依旧不是正式支持, 所以在 IDE 或者编辑器上会有报错。
  2. 编译需要指定额外的 -gcflags=-G=3 参数
代码语言:javascript
复制
go run -gcflags=-G=3 main.go

开始吧

不约束 any

首先,我们来一个最开放的约束, 就是不约束。

使用 [T any] 就好了。

demo 代码如下,

代码语言:javascript
复制
// demo1: 尝鲜泛型
package main

import (
	"fmt"
)

// printSlice 遍历传入的数组, 打印所有元素。
func printSlice[T any](s []T){
	for _, v:=range s{
		fmt.Printf("%v ",v)
	}

	fmt.Println("")
}

func main(){
  // 注意1: 在使用时, 强制为 T 指定类型, 例如这里的 [int]
	printSlice[int]([]int{666,777,888,999,1000})
	printSlice[string]([]string{"zhangsan", "lisi","wangwu"})
  
  // 注意2: 也可以不指定, golang 自己会进行类型约束检查。
  printSlice([]float32{1.1,2.2,3.3})
}

// go run -gcflags=-G=3 main.go
// 666 777 888 999 1000 
// zhangsan lisi wangwu 
// 1.1 2.2 3.3

在使用时, 需要注意:

  1. 执行函数时, 可以在函数名 和参数列表之间 使用 [type] 指定传入参数的类型,以便 强制约束 此次调用的传入参数类型, 其他符合 T 的类型也将不能传入。
  2. 也可以不指定, 那么 golang 会自动检查传入参数是否符合 T 类型。

使用内置类型约束

在约束 内置类型 时, 定义一个接口, Addable 在其中使用所支持的格式, 其作用有点像 typescript 中的的 联合类型

具体定义方式如下

Addable 就是接口名字, 也就是 [T Addable] 的类型。

注意

  1. 接口中, 使用 type 表示支持的类型
  2. 在多个支持类型之间,使用 逗号 , 进行分割
代码语言:javascript
复制
// Addable 定义类型约束
// 多个类型之间, 使用 逗号 , 分割
type Addable interface {
	type int,string
}

demo 如下

代码语言:javascript
复制
// demo2 使用内置类型约束
package main

import (
	"fmt"
)

// Addable 定义类型约束
// 多个类型之间, 使用 逗号 , 分割
type Addable interface {
	type int,string
}


func main() {

  // 1. 传入 string
	r:=add("hello", "jack")
	fmt.Println(r) // hellojack


  // 2. 传入 int
	r2:=add(1,2)
	fmt.Println(r2) // 3

  // 3. 传入 int64 // 失败
	r3:=add(int64(1),int64(2))
	fmt.Println(r3)
  // error: ./main.go:21:9: int64 does not satisfy Addable (int64 not found in int, string)
}

// add 对支持类型执行 + 操作
func add[T Addable](a,b T) T{
	return a+b
}

从结果所知,int64 不是之前 Addable 中所支持的类型, 所以报错了。 报错也很明显 not satisfy Addable 不符合接口。

因此, 以后在遇到泛型报错的时候, 多注意一下报错内容,看看是否是所支持类型错误, 而减少经验错误 明明 int64 支持加法,为什么不行呢?

使用接口方法约束

我们都知道, 接口本身就是一种约束行为。因此 go1.17 之前的接口思想, 同样适用。

代码中注释已经很清楚了, 就不再额外赘述解释了。

代码语言:javascript
复制
// demo3: 自定义接口方法约束
package main

import "fmt"
import "strconv"

// MyStringer 定义 T 的约束接口
// 只有具有 String() string 方法的类型才能进行 printer 操作
type MyStringer interface {
	String() string
}

// MyType 结构体 及 String 方法
type MyType struct {
	name string
}
func (t MyType) String() string{
	return "mytype.name = "+t.name
}

// YourType 结构体 及 方法
type YourType struct{
	age int
}
func (t YourType)String() string{
	return "yourtype.age = "+strconv.Itoa(t.age)
}


func main() {
  // 实例化
	mt:=MyType{
		name:"zhangsan",
	}
	printer(mt)

  // 实例化
	yt:=YourType{
		age:20,
	}
	printer(yt)
}

// printer 之支持满足 MyStringer 接口的类型
func printer[T MyStringer](vals T){
  // 打印结果
	fmt.Println(vals)
}

总结

总的来说, 在使用上, 泛型就是把之前的具体类型往上抽了一层 ,之前是使用 具体 的类型约束。现在是使用 某种接口 类型约束。

更多的,期待 go1.18 正式推出泛型的时候。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-08-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 熊猫云原生Go 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • go1.17 泛型尝鲜
    • 开始吧
      • 不约束 any
      • 使用内置类型约束
      • 使用接口方法约束
    • 总结
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档