Go 1.18 泛型实战

简介: Go 1.18 泛型实战

Go 1.18 泛型



上篇文章提及Go 1.18是第一个支持泛型的版本,那么什么是泛型呢?泛型程序设计(generic programming)是程序设计语言的一种风格或范式。泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型。


通常我们在写代码的时候,经常需要写很多重复的逻辑,一般这个时候我们就会使用函数来对其进行封装。但是由于Go是一种强类型语言,所以在定义和书写函数的时候需要在调用前标明类型。当然如果这一重复的逻辑只需要固定的类型,这样就足够了,但是很多时候我们需要不同的类型进行类似的逻辑,这样我们就会写很多相似的函数,总而言之不太优雅和简易。


看一个官网泛型示例


func main() {
 ints := map[string]int {
  "first": 12,
  "second": 13,
 }
 floats := map[string]float64 {
  "first": 12.00,
  "second": 13.00,
 }
 fmt.Println("ints 泛型求和:%v", SumIntsOrFloats(ints))
 fmt.Println("floats 泛型求和:%v", SumIntsOrFloats(floats))
}
func SumIntsOrFloats[K comparable, V int | float64 ](m map[K]V) V {
 var res V
 for _, v := range m {
  res += v
    }
 return res
}


[K comparable, V int | float64 ]这是泛型参数列表,它由两部分组成,其中K or V就是泛型参数,comparable or int or float64为泛型参数的约定或者就是泛型参数的类型;(m map[K]V)这是泛型函数参数,它的定义就依赖于前面泛型参数列表的声明。


注意:comparable是golang新引入的预定义标识符,是一个接口,指代可以使用==或!=来进行比较的类型集合。comparable仅能用于泛型中的类型限定(type constraint)。


运行看下结果:


ints 泛型求和:%v 25
floats 泛型求和:%v 25


其中V可以用接口约束比如:


// 接口
type Number interface {
 int | float64
}
func SumIntsOrFloats[K comparable, V Number ](m map[K]V) V {
 var res V
 for _, v := range m {
  res += v
 }
 return res
}

运行结果和上面一样的。


泛型支持接口约束


package main
import "fmt"
// Hi 接口
type Hi interface {
 A | B
 Hi()
}
type A struct {
 Aa string
 Cc string
}
type B struct {
 Bb string
 Cc string
}
// A实现Hi接口
func (a A) Hi() {
 fmt.Println(a.Aa)
}
// B实现Hi接口
func (b B) Hi() {
 fmt.Println(b.Bb)
}
// 泛型函数 T类型是接口类型(Hi)
func SayHi[T Hi](t T) {
 t.Hi()
}
func main() {
 a := A{"aa", "cc"}
 b := B{"bb", "cc"}
 SayHi(a)
 SayHi(b)
}


运行结果:


aa
bb


其实接口约束在泛型中比较常见,也比较容易理解,就是定义一个接口,其他类实现接口,但是因为要支持泛型,所以实现接口的类必须是接口的一部分,就像Hi中定义的那样。


小结


这只是Go泛型的冰山一角,想要了解很多泛型知识的同学还得到官网学习,泛型不是目的,写出真正优秀可维护的代码才是程序员孜孜不倦的唯一追求。官网参考:https://go.dev/ref/spec

相关文章
|
2月前
|
存储 算法 Go
go语言并发实战——日志收集系统(七) etcd的介绍与简单使用
go语言并发实战——日志收集系统(七) etcd的介绍与简单使用
|
13天前
|
安全 编译器 Go
Go 1.21: 泛型函数的全面回顾
Go 1.21: 泛型函数的全面回顾
|
1月前
|
安全 算法 程序员
在go语言中使用泛型和反射
【7月更文挑战第8天】本文介绍go支持泛型后,提升了代码复用,如操作切片、映射、通道的函数,以及自定义数据结构。 泛型适用于通用数据结构和函数,减少接口使用和类型断言。
110 1
在go语言中使用泛型和反射
|
17天前
|
存储 Go
带你入门 Go 语言中的泛型编程
带你入门 Go 语言中的泛型编程
26 0
|
2月前
|
监控 Go
go语言并发实战——日志收集系统(八) go语言操作etcd以及利用watch实现对键值的监控
go语言并发实战——日志收集系统(八) go语言操作etcd以及利用watch实现对键值的监控
go语言并发实战——日志收集系统(八) go语言操作etcd以及利用watch实现对键值的监控
|
2月前
|
存储 Go 索引
go语言并发实战——日志收集系统(一) 项目前言
go语言并发实战——日志收集系统(一) 项目前言
go语言并发实战——日志收集系统(一) 项目前言
|
1月前
|
存储 Go 索引
在go语言中自定义泛型的变长参数
【7月更文挑战第8天】在Go语言中,由于官方1.18以前的版本不支持泛型,可以通过空接口和反射模拟泛型。泛型适用于通用数据结构和函数,虽牺牲了一些性能,但提高了代码复用和类型安全性。
51 1
|
2月前
|
消息中间件 存储 监控
go语言并发实战——日志收集系统(六) 编写日志收集系统客户端
go语言并发实战——日志收集系统(六) 编写日志收集系统客户端
|
2月前
|
消息中间件 存储 Kafka
go语言并发实战——日志收集系统(二) Kafka简介
go语言并发实战——日志收集系统(二) Kafka简介
|
2月前
|
监控 Go
go语言并发实战——日志收集系统(十一)基于etcd来监视配置文件的变化
go语言并发实战——日志收集系统(十一)基于etcd来监视配置文件的变化