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

相关文章
|
3月前
|
消息中间件 人工智能 供应链
go-zero 微服务实战系列(二、服务拆分)
go-zero 微服务实战系列(二、服务拆分)
|
2月前
|
Shell Go API
Go语言grequests库并发请求的实战案例
Go语言grequests库并发请求的实战案例
|
3月前
|
分布式计算 安全 Java
简单易懂的 Go 泛型使用和实现原理介绍
简单易懂的 Go 泛型使用和实现原理介绍
|
2月前
|
安全 大数据 Go
深入探索Go语言并发编程:Goroutines与Channels的实战应用
在当今高性能、高并发的应用需求下,Go语言以其独特的并发模型——Goroutines和Channels,成为了众多开发者眼中的璀璨明星。本文不仅阐述了Goroutines作为轻量级线程的优势,还深入剖析了Channels作为Goroutines间通信的桥梁,如何优雅地解决并发编程中的复杂问题。通过实战案例,我们将展示如何利用这些特性构建高效、可扩展的并发系统,同时探讨并发编程中常见的陷阱与最佳实践,为读者打开Go语言并发编程的广阔视野。
|
3月前
|
安全 Java Go
Java&Go泛型对比
总的来说,Java和Go在泛型的实现和使用上各有特点,Java的泛型更注重于类型安全和兼容性,而Go的泛型在保持类型安全的同时,提供了更灵活的类型参数和类型集的概念,同时避免了运行时的性能开销。开发者在使用时可以根据自己的需求和语言特性来选择使用哪种语言的泛型特性。
49 7
|
3月前
|
消息中间件 缓存 Kafka
go-zero微服务实战系列(八、如何处理每秒上万次的下单请求)
go-zero微服务实战系列(八、如何处理每秒上万次的下单请求)
|
3月前
|
缓存 NoSQL Redis
go-zero微服务实战系列(七、请求量这么高该如何优化)
go-zero微服务实战系列(七、请求量这么高该如何优化)
|
3月前
|
缓存 NoSQL 数据库
go-zero微服务实战系列(五、缓存代码怎么写)
go-zero微服务实战系列(五、缓存代码怎么写)
|
3月前
|
API
企业项目迁移go-zero实战(二)
企业项目迁移go-zero实战(二)
|
3月前
|
消息中间件 存储 NoSQL
redis实战——go-redis的使用与redis基础数据类型的使用场景(一)
本文档介绍了如何使用 Go 语言中的 `go-redis` 库操作 Redis 数据库
181 0
redis实战——go-redis的使用与redis基础数据类型的使用场景(一)