当前位置:网站首页>golang generics
golang generics
2022-08-02 06:12:00 【m0_67394006】
泛型
go1.18版本开始支持
在函数上使用[T 支持的类型] 表示泛型,比如
func AddSum[T int|float64](params ...T)(sum T){
// 一些操作
return sum
}
自带泛型:
- any 表示任何类型,即interface
- 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})
}
参考
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在.深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小.自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前.因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担.添加下方名片,即可获取全套学习资料哦
边栏推荐
- Mysql implements optimistic locking
- navicat连接MySQL报错:1045 - Access denied for user ‘root‘@‘localhost‘ (using password YES)
- mysql实现按照自定义(指定顺序)排序
- JUC(一)- JUC学习概览 - 对JUC有一个整体的认识
- 编译失败:HBuilderX 安装目录不能包括 ( 等特殊字符 (HBuilderX,uni-app报错)
- MySQL 字符串拼接 - 多种字符串拼接实战案例
- leetcode 665. Non-decreasing Array 非递减数列(中等)
- Redis-集群模式(主从复制模式,哨兵模式,集群化模式)
- 简道云-灵活易用的应用搭建平台
- 去字节跳动自动化测试二面原题(根据录音整理)真实有效 26
猜你喜欢

Introduction to Grid Layout

Matlab论文插图绘制模板第41期—气泡图(bubblechart)

力扣 2127. 参加会议的最多员工数 拓扑剪枝与2360补充

MySQL如何对SQL做prepare预处理(解决IN查询SQL预处理仅能查询出一条记录的问题)

MySQL导入sql文件的三种方法
![[PSQL] 窗口函数、GROUPING运算符](/img/95/5c9dc06539330db907d22f84544370.png)
[PSQL] 窗口函数、GROUPING运算符

Navicat cannot connect to mysql super detailed processing method

面试测试工程师一般会问什么?测试主管告诉你

2021年软件测试面试题大全

区块元素、内联元素(<div>元素、span元素)
随机推荐
ELK log analysis system
golang的time包:时间间隔格式化和秒、毫秒、纳秒等时间戳格式输出的方法
navicat连接MySQL报错:1045 - Access denied for user ‘root‘@‘localhost‘ (using password YES)
JDBC revisited
prisma使用mongodb副本集群报错引发的一些列问题
[PSQL] window function, GROUPING operator
元空间内存溢出
本周大新闻|苹果MR已进行Pre-EVT测试,Quest 2涨价100美元
mysql 存储过程详解
JUC(二)原子类:CAS、乐观锁、Unsafe和原子类
Timing task library in the language use Cron, rounding
大屏UI设计-看这一篇就够了
Redis常见题型
公司不重视软件测试,新来的阿里P8给我们撰写了测试用例编写规范
Go语言之interface详解
MySQL 的 limit 分页查询及性能问题
12个MySQL慢查询的原因分析
navicat新建数据库
Navicat new database
mysql 查询表 所有字段