GO语言之泛型应用

简介: 本文介绍了Go语言中泛型的使用,包括为何引入泛型、泛型语法详解以及如何自定义约束。通过实例展示了泛型在简化代码、提高复用性方面的优势,并演示了泛型在slice、指针、map等数据类型中的应用。

在之前都未接触过泛型,在之前偶然听别人提及过泛型这东西,所以就学习总结一下go的泛型使用

一、为什么泛型会在新版的go中加入?


一个简单的例子来比较用泛型和不用泛型的区别

  • 需求:封装一个函数来实现对多种类型(int、float...)进行加法运算

由于函数的入参的类型只能定义一个

go

体验AI代码助手

代码解读

复制代码

func sumInt(a, b int) int {
	return a + b
}

所以我们只能使用interface作为入参在利用反射进行类型判断来实现

go

体验AI代码助手

代码解读

复制代码

func sum_Int_Float(a, b interface{}) interface{} {
  switch a.(type) {
  case int:
    a1 := a.(int)
    b1 := b.(int)
    return a1 + b1
  case float64:
    a1 := a.(float64)
    b1 := b.(float64)
    return a1 + b1
  default:
    return nil
  }
}

但是使用泛型的话那么将是这个样子

go

体验AI代码助手

代码解读

复制代码

func sum_Int_Float[T int|float64](a,b T) T {
  return a + b
}

这样看下来使用泛型会简洁很多


二、泛型语法详解

一个简单的泛型大概是这样的

go

体验AI代码助手

代码解读

复制代码

func MyPrintln[T any](a T) {
	fmt.Println(a)
}

func main() {
	MyPrintln("nb")
    //运行结果:
	//nb
}

MyType[T1 constraint1 | constraint2, T2 constraint3...] ...

  • MyType可以是函数名, 结构体名, 类型名…
  • T1, T2…是泛型名, 可以随便取
  • constraint的意思是约束,是泛型中最重要的概念, T满足其中之一即可(如T1可以是constraint1和constraint2中的任何一个)

三、constraint约束

在之前的例子中func MyPrintln[T any](a T)any就是一个约束 不过看any的底层代码type any = interface{}可知any就跟interface一样


而go中的约束大概是有这些

any(interface{} Interger Float comparable (可比较) ...


自定义constraint

然后我们可以看看constraint包里的约束是怎么构造的,然后我们就可以自定义constraint(但是正式版的constraints已经被去除掉了,详细原因

go

体验AI代码助手

代码解读

复制代码

// Integer is a constraint that permits any integer type.
// If future releases of Go add new predeclared integer types,
// this constraint will be modified to include them.
type Integer interface {
	Signed | Unsigned
}

// Float is a constraint that permits any floating-point type.
// If future releases of Go add new predeclared floating-point types,
// this constraint will be modified to include them.
type Float interface {
	~float32 | ~float64
}
//......

由此我们可知道怎样去自定义约束了

例如我们想定义一个map,限制它的k,v的类型

go

体验AI代码助手

代码解读

复制代码

type myCompare interface {
	~int | ~float64 | [5]interface{} | struct{}
}

type myint interface {
	~int8|~int64
}
type myfloat interface {
	~float64|~float32
}

type MyMap[K myCompare, V myfloat | myint] map[K]V

这样子我们就定义了一个自己的map


  • 除map外,定义泛型结构体变量:

go

体验AI代码助手

代码解读

复制代码

type Struct1 [T string|int|float64] struct {
  Title string
  Content  T
}

而对于结构体,结构体可以进行匿名操作 即把结构体的申明定义和初始化一起完成,举个例子

go

体验AI代码助手

代码解读

复制代码

stu := struct{
  Name string
  Age int
  Weight float64
}{
  "smallyang",
  18,
  50.5,
}
fmt.Println("Student =", stu) // Student = {smallyang 18 50.5}

但是如果对泛型定义的结构体是不支持匿名的

go

体验AI代码助手

代码解读

复制代码

stu2 := struct[T int|float64] {
  Name   string
  Age    int
  Weight T
}[int]{
  "smallyang",
  18,
  50,
}
fmt.Println("Student =", stu2)

/*
./main.go:70:16: syntax error: unexpected [, expecting {
./main.go:72:10: syntax error: unexpected int at end of statement
./main.go:73:10: syntax error: unexpected T at end of statement
./main.go:74:3: syntax error: unexpected [ after top level declaration
*/

  • 泛型数组变量:

go

体验AI代码助手

代码解读

复制代码

type slice[T any] []T

等等...


四、泛型中操作各种数据类型的例子示范

1、操作slice

go

体验AI代码助手

代码解读

复制代码

package main

import (
	"fmt"
)

type slice[T any] []T

type mySlice interface {  自定义constraint
	~int | ~string
}

func printSlice[T mySlice](s []T) {
	for _, v := range s {
		fmt.Printf("%v ", v)
	}
	fmt.Print("\n")
}

func main() {
	vs := slice[int]{1, 2, 3, 4}
	printSlice(vs)

	vs2 := slice[string]{"a", "b"}
	printSlice(vs2)
}

2、操作指针

go

体验AI代码助手

代码解读

复制代码

package main
 
import (
  "fmt"
)
 
func pointerOf[T any](v T) *T {
  return &v
}
 
func main() {
  sp := pointerOf("foo")
  fmt.Println(*sp)
 
  ip := pointerOf(123)
  fmt.Println(*ip)
  *ip = 234
  fmt.Println(*ip)
}

3、操作map

go

体验AI代码助手

代码解读

复制代码

package main
 
import (
  "fmt"
)
 
func mapFunc[T any, M any](a []T, f func(T) M) []M {
  n := make([]M, len(a), cap(a))
  for i, e := range a {
    n[i] = f(e)
  }
  return n
}
 
func main() {
  vi := []int{1, 2, 3, 4, 5, 6}
  vs := mapFunc(vi, func(v int) string {
    return "<" + fmt.Sprint(v*v) + ">"
  })
  fmt.Println(vs)
}


转载来源:https://juejin.cn/post/7271459513094406203

相关文章
|
2月前
|
消息中间件 缓存 NoSQL
Redis各类数据结构详细介绍及其在Go语言Gin框架下实践应用
这只是利用Go语言和Gin框架与Redis交互最基础部分展示;根据具体业务需求可能需要更复杂查询、事务处理或订阅发布功能实现更多高级特性应用场景。
275 86
|
4月前
|
算法 Go
Go 语言泛型 — 泛型语法与示例
本文详解 Go 语言泛型语法与使用示例,涵盖泛型函数、类型声明、类型约束及实战应用,适合入门学习与开发实践。
|
6月前
|
人工智能 监控 安全
Go通道机制与应用详解
本文全面解析了Go语言中的通道(Channel),从基础概念到高级应用,涵盖创建、操作、垃圾回收及实际场景使用。通道作为Go并发模型的核心,支持协程间安全高效的数据通信与同步。文章介绍了无缓冲和有缓冲通道的特性,以及发送、接收、关闭等操作,并探讨了`select`语句、超时处理、遍历通道等高级用法。此外,还深入分析了通道的垃圾回收机制,包括引用计数、生命周期管理和循环引用问题。最后通过数据流处理、任务调度和状态监控等实例,展示了通道在实际开发中的广泛应用。理解通道不仅有助于构建高并发系统,还能优化资源管理,提升程序性能。
216 31
|
1月前
|
Java 编译器 Go
【Golang】(5)Go基础的进阶知识!带你认识迭代器与类型以及声明并使用接口与泛型!
好烦好烦好烦!你是否还在为弄不懂Go中的泛型和接口而烦恼?是否还在苦恼思考迭代器的运行方式和意义?本篇文章将带你了解Go的接口与泛型,还有迭代器的使用,附送类型断言的解释
160 3
|
9月前
|
运维 监控 算法
监控局域网其他电脑:Go 语言迪杰斯特拉算法的高效应用
在信息化时代,监控局域网成为网络管理与安全防护的关键需求。本文探讨了迪杰斯特拉(Dijkstra)算法在监控局域网中的应用,通过计算最短路径优化数据传输和故障检测。文中提供了使用Go语言实现的代码例程,展示了如何高效地进行网络监控,确保局域网的稳定运行和数据安全。迪杰斯特拉算法能减少传输延迟和带宽消耗,及时发现并处理网络故障,适用于复杂网络环境下的管理和维护。
|
11月前
|
存储 监控 算法
员工上网行为监控中的Go语言算法:布隆过滤器的应用
在信息化高速发展的时代,企业上网行为监管至关重要。布隆过滤器作为一种高效、节省空间的概率性数据结构,适用于大规模URL查询与匹配,是实现精准上网行为管理的理想选择。本文探讨了布隆过滤器的原理及其优缺点,并展示了如何使用Go语言实现该算法,以提升企业网络管理效率和安全性。尽管存在误报等局限性,但合理配置下,布隆过滤器为企业提供了经济有效的解决方案。
207 8
员工上网行为监控中的Go语言算法:布隆过滤器的应用
|
7月前
|
监控 Java Go
无感改造,完美监控:Docker 多阶段构建 Go 应用无侵入观测
本文将介绍一种基于 Docker 多阶段构建的无侵入 Golang 应用观测方法,通过此方法用户无需对 Golang 应用源代码或者编译指令做任何改造,即可零成本为 Golang 应用注入可观测能力。
402 85
|
4月前
|
Java Shell Maven
【Azure Container App】构建Java应用镜像时候遇无法编译错误:ERROR [build 10/10] RUN ./mvnw.cmd dependency:go-offline -B -Dproduction package
在部署Java应用到Azure Container App时,构建镜像过程中出现错误:“./mvnw.cmd: No such file or directory”。尽管项目根目录包含mvnw和mvnw.cmd文件,但依然报错。问题出现在Dockerfile构建阶段执行`./mvnw dependency:go-offline`命令时,系统提示找不到可执行文件。经过排查,确认是mvnw文件内容异常所致。最终通过重新生成mvnw文件解决该问题,镜像成功构建。
165 1
|
4月前
|
存储 安全 算法
Go语言泛型-泛型对代码结构的优化
Go语言自1.18版本引入泛型,极大提升了代码的通用性与可维护性。通过泛型,开发者可以减少重复代码、提高类型安全性,并增强程序的复用性和可读性。本文详细介绍了泛型在数据结构、算法及映射功能中的应用,展示了其在优化代码结构方面的优势。同时,Go编译器对泛型代码进行类型推导,确保运行时性能不受影响。合理使用泛型,有助于构建更加灵活高效的程序。
|
4月前
|
分布式计算 算法 安全
Go语言泛型-泛型约束与实践
Go语言中的泛型约束用于限制类型参数的范围,提升类型安全性。通过接口定义约束,可实现对数值类型、排序与比较等操作的支持。开发者既可使用标准库提供的预定义约束,如constraints.Ordered和constraints.Comparable,也可自定义约束以满足特定需求。泛型广泛应用于通用数据结构(如栈、队列)、算法实现(如排序、查找)及构建高效可复用的工具库,使代码更简洁灵活。
下一篇
oss云网关配置