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入门实战:并发模式的使用
本文详细探讨了Go语言的并发模式,包括Goroutine、Channel、Mutex和WaitGroup等核心概念。通过具体代码实例与详细解释,介绍了这些模式的原理及应用。同时分析了未来发展趋势与挑战,如更高效的并发控制、更好的并发安全及性能优化。Go语言凭借其优秀的并发性能,在现代编程中备受青睐。
107 33
|
1月前
|
Go
【LeetCode 热题100】DP 实战进阶:最长递增子序列、乘积最大子数组、分割等和子集(力扣300 / 152/ 416 )(Go语言版)
本文深入解析三道经典的动态规划问题:**最长递增子序列(LIS)**、**乘积最大子数组** 和 **分割等和子集**。 - **300. LIS** 通过 `dp[i]` 表示以第 `i` 个元素结尾的最长递增子序列长度,支持 O(n²) 动态规划与 O(n log n) 的二分优化。 - **152. 乘积最大子数组** 利用正负数特性,同时维护最大值与最小值的状态转移方程。 - **416. 分割等和子集** 转化为 0-1 背包问题,通过布尔型 DP 实现子集和判断。 总结对比了三题的状态定义与解法技巧,并延伸至相关变种问题,助你掌握动态规划的核心思想与灵活应用!
52 1
【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)
本文讲解了两道经典的图论问题:**岛屿数量(LeetCode 200)** 和 **腐烂的橘子(LeetCode 994)**,分别通过 DFS/BFS 实现。在“岛屿数量”中,利用深度或广度优先搜索遍历二维网格,标记连通陆地并计数;“腐烂的橘子”则采用多源 BFS,模拟腐烂传播过程,计算最短时间。两者均需掌握访问标记技巧,是学习网格搜索算法的绝佳实践。
63 1
|
1月前
|
Go
【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)
本篇博客详细解析了三道经典的动态规划问题:198. 打家劫舍(线性状态转移)、279. 完全平方数与322. 零钱兑换(完全背包问题)。通过 Go 语言实现,帮助读者掌握动态规划的核心思想及其实战技巧。从状态定义到转移方程,逐步剖析每道题的解法,并总结其异同点,助力解决更复杂的 DP 问题。适合初学者深入理解动态规划的应用场景和优化方法。
42 0
MCP 实战:用 Go 语言开发一个查询 IP 信息的 MCP 服务器
随着 MCP 的快速普及和广泛应用,MCP 服务器也层出不穷。大多数开发者使用的 MCP 服务器开发库是官方提供的 typescript-sdk,而作为 Go 开发者,我们也可以借助优秀的第三方库去开发 MCP 服务器,例如 ThinkInAIXYZ/go-mcp。 本文将详细介绍如何在 Go 语言中使用 go-mcp 库来开发一个查询 IP 信息的 MCP 服务器。
178 0
Go语言实战:错误处理和panic_recover之自定义错误类型
本文深入探讨了Go语言中的错误处理和panic/recover机制,涵盖错误处理的基本概念、自定义错误类型的定义、panic和recover的工作原理及应用场景。通过具体代码示例介绍了如何定义自定义错误类型、检查和处理错误值,并使用panic和recover处理运行时错误。文章还讨论了错误处理在实际开发中的应用,如网络编程、文件操作和并发编程,并推荐了一些学习资源。最后展望了未来Go语言在错误处理方面的优化方向。
Go语言grequests库并发请求的实战案例
Go语言grequests库并发请求的实战案例
简单易懂的 Go 泛型使用和实现原理介绍
简单易懂的 Go 泛型使用和实现原理介绍
深入探索Go语言并发编程:Goroutines与Channels的实战应用
在当今高性能、高并发的应用需求下,Go语言以其独特的并发模型——Goroutines和Channels,成为了众多开发者眼中的璀璨明星。本文不仅阐述了Goroutines作为轻量级线程的优势,还深入剖析了Channels作为Goroutines间通信的桥梁,如何优雅地解决并发编程中的复杂问题。通过实战案例,我们将展示如何利用这些特性构建高效、可扩展的并发系统,同时探讨并发编程中常见的陷阱与最佳实践,为读者打开Go语言并发编程的广阔视野。
AI助理

你好,我是AI助理

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

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问