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

目录
打赏
0
0
0
0
5
分享
相关文章
Go语言grequests库并发请求的实战案例
Go语言grequests库并发请求的实战案例
深入探索Go语言并发编程:Goroutines与Channels的实战应用
在当今高性能、高并发的应用需求下,Go语言以其独特的并发模型——Goroutines和Channels,成为了众多开发者眼中的璀璨明星。本文不仅阐述了Goroutines作为轻量级线程的优势,还深入剖析了Channels作为Goroutines间通信的桥梁,如何优雅地解决并发编程中的复杂问题。通过实战案例,我们将展示如何利用这些特性构建高效、可扩展的并发系统,同时探讨并发编程中常见的陷阱与最佳实践,为读者打开Go语言并发编程的广阔视野。
go-zero微服务实战系列(十、分布式事务如何实现)
go-zero微服务实战系列(十、分布式事务如何实现)
go-zero微服务实战系列(九、极致优化秒杀性能)
go-zero微服务实战系列(九、极致优化秒杀性能)
go-zero微服务实战系列(八、如何处理每秒上万次的下单请求)
go-zero微服务实战系列(八、如何处理每秒上万次的下单请求)
go-zero微服务实战系列(七、请求量这么高该如何优化)
go-zero微服务实战系列(七、请求量这么高该如何优化)
go-zero微服务实战系列(六、缓存一致性保证)
go-zero微服务实战系列(六、缓存一致性保证)
go-zero微服务实战系列(五、缓存代码怎么写)
go-zero微服务实战系列(五、缓存代码怎么写)
go-zero微服务实战系列(四、CRUD热身)
go-zero微服务实战系列(四、CRUD热身)
go-zero微服务实战系列(三、API定义和表结构设计)
go-zero微服务实战系列(三、API定义和表结构设计)

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等