首页 > 其他分享 >深入浅出Go语言:泛型入门指南

深入浅出Go语言:泛型入门指南

时间:2024-03-01 17:44:25浏览次数:24  
标签:型函数 深入浅出 约束 Go 参数 类型 泛型

深入浅出Go语言:泛型入门指南

原创 麻凡 麻凡 2024-03-01 09:00 湖南 听全文

随着Go 1.18版本的发布,泛型正式成为了Go语言的一部分。泛型为Go开发者带来了更强大的类型抽象能力,允许我们编写更加灵活和可复用的代码。本文将带你了解Go泛型的基础知识,让你快速上手这一新特性。

什么是泛型

泛型(Generics)是一种编程语言特性,它允许程序员在定义函数、类型或接口时,使用类型参数(Type Parameters)来代替具体的类型。这样,当使用泛型代码时,可以为类型参数指定具体的类型,从而实现代码的灵活性和可复用性。

在Go 1.18中,泛型通过引入类型参数和约束(Constraint)来实现。类型参数用于声明泛型函数或类型,而约束则用于限制类型参数的取值范围。

泛型的基本使用

在没有泛型之前,如果需要编写一个函数来处理不同类型的数据,通常需要为每种类型编写一个独立的函数。这会导致大量重复的代码和维护成本。而有了泛型,我们可以编写一个通用的函数来处理多种类型的数据。

下面是一个简单的示例,展示如何使用泛型来编写一个通用的打印函数:

package main    
import "fmt"    

// Print 泛型函数,可以打印任意类型的数据  
func Print[T any](v T) {      
 fmt.Println(v)  
}    

func main() {      
 Print(123)       // 输出: 123      
 Print("hello")   // 输出: hello      
 Print(3.14)      // 输出: 3.14  
}

在上面的示例中,我们定义了一个名为Print的泛型函数。它接受一个类型参数T,并且没有指定任何约束(使用any表示接受任意类型)。然后,在函数体内使用fmt.Println打印传入的参数。在main函数中,我们可以调用Print函数来打印不同类型的数据。

约束

虽然上面的示例展示了泛型的基本用法,但在实际开发中,我们通常需要对类型参数进行一定的约束。约束用于限制类型参数的取值范围,确保传入的类型满足泛型函数或类型的要求。

在Go中,约束是通过接口类型来实现的。我们可以定义一个接口类型来作为约束,并在类型参数声明时使用该接口类型来限制类型参数的取值范围。例如,如果我们希望编写一个泛型函数来比较两个值的大小,我们可以定义一个约束来限制类型参数必须支持比较操作:

package main    
import "fmt"    

// Comparable 约束接口,要求类型必须支持比较操作  
type Comparable interface {      
 type int, 
 float64, 
 string // 这里列出了支持比较操作的具体类型,但实际上应该使用更通用的约束方式(待Go官方完善)  
}    

// Max 泛型函数,返回两个值中的较大值(这里使用了一个假设的约束语法,实际上Go 1.18的约束语法与此略有不同)  
func Max[T Comparable](a, b T) T {      
 if a > b { 
 // 这里假设T类型的值支持>操作符(实际上需要根据具体的约束来判断)
 return a      
 }      
 return b  
}    

func main() {      
 fmt.Println(Max(3, 5))       // 输出: 5(假设int类型支持Comparable约束)
 fmt.Println(Max(2.0, 3.5))   // 输出: 3.5(假设float64类型支持Comparable约束)      
   // fmt.Println(Max("a", "b")) // 编译错误,因为string类型不支持>操作符(实际上应该根据具体的约束来判断是否支持)  
}

需要注意的是,上面的示例中使用了一个假设的约束语法来演示如何对类型参数进行约束。在Go 1.18中,实际的约束语法与此略有不同。由于篇幅限制,这里不再展开详细的约束语法和用法。建议查阅Go官方文档或相关教程以获取更准确的信息。

此外,还需要注意的是,在Go 1.18中,泛型的支持还处于初步阶段,并且存在一些限制和不足之处。例如,目前还不能在泛型函数或类型中使用类型断言或类型切换等操作。但随着Go语言的不断发展和完善,相信泛型将会变得更加强大和灵活。

麻凡 码农一枚,爱折腾,分享技术、副业与生活思考。在未知路上,一起挖坑填坑,探索无限可能。 24篇原创内容 公众号   麻凡

 一份鼓励,一份认可! 

赞赏二维码喜欢作者

深入浅出Go语言20 编程语言19 深入浅出Go语言 · 目录 上一篇深入浅出Go语言:互斥锁与通道解决并发编程中的竞争条件 阅读 86 麻凡 ​ 喜欢此内容的人还喜欢   深入浅出Go语言:Go语言中的Map使用详解     我看过的号 麻凡 不看的原因   基于FX构建大型Golang应用     我看过的号 DeepNoMind 不看的原因   软件设计的全方位解决方案:整合领域驱动设计、UML和4+1架构视图模型     我关注的号 运维开发王义杰 不看的原因   作者已设置关注后才可以留言              

人划线

标签:型函数,深入浅出,约束,Go,参数,类型,泛型
From: https://www.cnblogs.com/cheyunhua/p/18047605

相关文章

  • 【STL和泛型编程】4. hashtable、unordered_set、unordered_map
    1.hashtable前置知识:【数据结构】3.跳表和散列 基本原理:将Key计算成一个数值,然后取余数得到它在表头中的位置table(篮子)里每个指针都指向一个链表(桶)来存储余数相同的值如果桶内的元素个数比篮子个数还多,则将篮子的大小扩充篮子是vector,数量是质数,初始为53,53扩充后为97......
  • 为什么django3+版本不能用sql_server.pyodbc只能用mssql
    之前使用的是django2.2.2,后来换到django3.2后发现在settings中进行数据库链接sqlserver的时候sql_server.pyodbc用不了,随后切换到mssql才行,后来查阅后发现是版本问题导致 Django3.2本身不包含对SQLServer的直接支持。默认情况下,Django支持几种主流的数据库后端,例如SQLi......
  • 解决celery与django结合后,分别启动celery和django的进程同时调用定时任务的问题
     django中引入celery后发现在代码中写如下这样的定时任务,启动celery和django的工程后,他们都会调用这个定时任务导致,任务有的时候会冲突出现奇怪的问题。如何解决请继续看。scheduler=BackgroundScheduler()scheduler.add_job(testFunc,'interval',seconds=60)scheduler.......
  • Go语言精进之路读书笔记第41条——有层次地组织测试代码
    聚焦位于测试包内的测试代码该如何组织41.1经典模式—平铺测试函数各自独立,测试函数之间没有层级关系,所有测试平铺在顶层41.2Unit家族模式测试套件(TestSuite)和测试用例(TestCase)41.3测试固件测试固件是一个人造的、确定性的缓解,在这个环境中进行测试,测试结果是可重复的......
  • MongoDB 聚合
    MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。有点类似sql语句中的count(*)。aggregate()方法MongoDB中聚合的方法使用​aggregate()​。语法​aggregate()​方法的基本语法格式如下所示:>db.COLLECTION_NAME.aggregate(AGGR......
  • MongoDB 索引
    索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。索引是特殊的数据结构,索引存......
  • vminsert 依赖之GoGoProtos
      publicfinalclassGoGoProtos{privateGoGoProtos(){}publicstaticvoidregisterAllExtensions(com.google.protobuf.ExtensionRegistryLiteregistry){registry.add(GoGoProtos.goprotoEnumPrefix);registry.add(GoGoProtos.......
  • golang wire依赖注入
    安装gogetgithub.com/google/wire/cmd/wire@latest一.假设需要定义多个有依赖的启动项,新建main.gopackagemainimport("fmt")typeMessagestringfuncNewMessage()Message{returnMessage("Hithere!")}typeEventstruct{GreeterGreeter}......
  • go: 协程生命周期控制
    go:协程生命周期控制原创 王义杰 运维开发王义杰 2024-02-2822:27 广东 听全文在go开发中,如果我们希望在一定条件下,比如执行了某些任务后,主动结束其它相关的协程,可以通过使用context包来实现。context包允许我们发送取消信号给一个或多个协程,这样我们就可以控制协......
  • Go 100 mistakes - #86: Sleeping in unit tests
      ......