当前位置: 首页 > article >正文

Go 语言从入门到进阶 | 第 7 章:泛型(Generics)

系列:Go 语言从入门到进阶作者:耿雨飞适用版本:go v1.26.2前置条件在开始本章学习之前,请确保:已完成第 1 ~ 6 章的学习,掌握接口、类型断言和类型 switch理解接口的隐式实现机制和方法集规则已获取 Go 1.26.2 源码树(go-go1.26.2目录)导读Go 1.18 引入了泛型(Generics),这是 Go 语言自诞生以来最大的语法扩展。在此之前,通用数据结构和算法只能通过interface{}或代码生成实现,要么牺牲类型安全,要么增加维护成本。泛型的引入让我们可以编写类型安全的通用代码,同时保持 Go 一贯的简洁风格。Go 的泛型设计独具特色——它使用**类型约束(Type Constraints)**来限制类型参数的能力范围,而类型约束本身就是接口。这意味着泛型与 Go 已有的接口体系无缝融合,而非引入一套全新的概念。本章将从泛型基础语法出发,逐步深入到类型约束的进阶用法,最后结合slices、maps、cmp三个标准库泛型包的源码,展示泛型在实际工程中的应用。本章将对照 Go 1.26.2 源码中的以下关键路径:源码路径内容说明src/builtin/builtin.go:97any约束的定义——interface{}的别名src/builtin/builtin.go:104comparable约束的定义src/cmp/cmp.gocmp.Ordered约束、cmp.Compare、cmp.Less、cmp.Or函数src/slices/slices.go泛型切片操作:Equal、Index、Contains、Insert、Delete、Clone、Compact、Reverse等src/slices/sort.go泛型排序:Sort、SortFunc、BinarySearch、Min、Max等src/maps/maps.go泛型映射操作:Equal、Clone、Copy、DeleteFuncsrc/maps/iter.go泛型映射迭代器:All、Keys、Values、Insert、Collect学习目标完成本章后,你将能够:理解类型参数和类型约束的语法,编写泛型函数和泛型类型掌握any和comparable两个内建约束的含义与适用场景理解~近似约束符的作用,能够定义自定义约束接口从源码层面理解cmp.Ordered约束的设计熟练使用slices、maps、cmp标准库泛型包理解泛型与接口的关系,做出合理的设计选择7.1 泛型基础7.1.1 为什么需要泛型在泛型引入之前,编写通用函数有两种选择,都不理想:方式一:为每种类型重复编写funcContainsInt(s[]int,vint)bool{for_,x:=ranges{ifx==v{returntrue}}returnfalse}funcContainsString(s[]string,vstring)bool{for_,x:=ranges{ifx==v{returntrue}}returnfalse}// 还有 ContainsFloat64、ContainsBool... 无穷无尽方式二:使用 interface{},牺牲类型安全funcContains(s[]any,v any)bool{for_,x:=ranges{ifx==v{returntrue}}returnfalse}// 调用时需要手动转换类型,且编译器无法检查类型匹配// Contains([]any{1, 2, 3}, "hello") // 编译通过,但逻辑错误方式三(Go 1.18+):泛型——类型安全且通用funcContains[E comparable](s[]E,v E)bool{for_,x:=ranges{ifx==v{returntrue}}returnfalse}// 编译期类型安全Contains([]int{1,2,3},42)// OKContains([]string{"a","b"},"b")// OK// Contains([]int{1, 2, 3}, "hello") // 编译错误!类型不匹配7.1.2 类型参数(Type Parameters)类型参数是泛型的核心语法。在函数名或类型名后用方括号[]声明类型参数:func函数名[T 约束](参数列表)返回值列表{// T 在函数体中可以当做类型使用}packagemainimport"fmt"// 单个类型参数funcPrint[T any](v T){fmt.Println(v)}// 多个类型参数funcPair[K,V any](k K,v V)string{returnfmt.Sprintf("(%v, %v)",k,v)}// 类型参数用于返回值funcZero[T any]()T{varzero Treturnzero}funcmain(){// 显式指定类型参数Print[int](42)Print[string]("hello")// 类型推断——编译器自动推断 TPrint(3.14)// T 推断为 float64Print(true)// T 推断为 boolfmt.Println(Pair("name",42))// (name, 42)fmt.Println(Zero[int]())// 0fmt.Println(Zero[string]())// ""fmt.Println(Zero[bool]())// false}类型推断规则:编译器根据传入的实参类型推断类型参数。大多数情况下无需显式指定类型参数,但在以下场景中需要显式指定:类型参数只出现在返回值(如Zero[int]())需要消除歧义时7.1.3 类型约束(Type Constraints)类型约束限制了类型参数可以接受的类型范围。在 Go 中,类型约束就是接口:// any 约束:接受任何类型funcPrint[T any](v T){...}// comparable 约束:接受所有可比较的类型(支持 == 和 !=)funcContains[E comparable](s[]E,v E)bool{...}// 自定义接口约束typeStringerinterface{String()string}funcPrintString[T Stringer](v T){fmt.Println(v.String())}7.1.4 any 约束any是interface{}的别名,定义在src/builtin/builtin.go:97:// src/builtin/builtin.go:96-97// any is an alias for interface{} and is equivalent to interface{} in all ways.typeany=interface{}any约束允许传入任何类型,但这也意味着在函数体内你只能对T做最基本的操作——赋值、取地址、作为any使用:funcIdentity[T any](v T)T{returnv// OK:赋值和返回}funcBroken[T any](a,b T)bool{// return a == b // 编译错误!any 不保证支持 ==// return a + b // 编译错误!any 不保证支持 +_=a_=breturnfalse}7.1.5 comparable 约束comparable是一个特殊的内建约束,定义在src/builtin/builtin.go:99-104:// src/builtin/builtin.go:99-104// comparable is an interface that is implemented by all comparable types// (booleans, numbers, strings, pointers, channels, arrays of comparable types,// structs whose fields are all comparable types).// The comparable interface may only be used as a type parameter constraint,// not as the type of a variable.typecomparableinterface{comparable}comparable约束允许对类型参数使用==和!=运算符:packagemainimport"fmt"funcIndexOf[E comparable](s[]E,v E)int{fori,x:=ranges{ifx==v{// comparable 保证了 == 可用returni}}return-1}funcmain(){fmt.Println(IndexOf([]int{10,20,30},20))// 1fmt.Println(IndexOf([]string{"a","b","c"},"b"))// 1fmt.Println(IndexOf([]float64{1.1,2.2,3.3},2.2))// 1// 以下不能编译——切片不是 comparable 类型// IndexOf([][]int{ {1}, {2}}, []int{1}) // 编译错误}comparable 涵盖的类型:类型类别示例可比较布尔boolYes数值int,float64,complex128Yes字符串stringYes指针*int,*MyStructYesChannelchan intYes数组[3]int(元素可比较时)Yes结构体struct{X int}(字段都可比较时)Yes切片[]intNoMapmap[string]intNo函数func()No7.2 泛型函数与泛型类型7.2.1 泛型函数定义与调用泛型函数可以有复杂的类型参数和约束组合:packagemainimport"fmt"// 返回两个值中较大的那个funcMax[Tinterface{~int|~float64|~string}](a,b T)T{ifab{returna}returnb}// 过滤切片:返回满足条件的元素funcFilter[T any](s[]T,ffunc(T)bool)[]T{varresult[]Tfor_,v:=ranges{iff(v){result=append(result,v)}}returnresult}// Map 转换:将 []T 转为 []UfuncMap[T,U any](s[]T,ffunc(T)U)[]U

相关文章:

Go 语言从入门到进阶 | 第 7 章:泛型(Generics)

系列:Go 语言从入门到进阶 作者:耿雨飞 适用版本:go v1.26.2 前置条件 在开始本章学习之前,请确保: 已完成第 1 ~ 6 章的学习,掌握接口、类型断言和类型 switch 理解接口的隐式实现机制和方法集规则 已获取 Go 1.26.2 源码树(go-go1.26.2 目录) 导读 Go 1.18 引入了泛…...

架构创新与性能突破:DeepFilterNet全频段实时语音增强技术解决方案

架构创新与性能突破:DeepFilterNet全频段实时语音增强技术解决方案 【免费下载链接】DeepFilterNet Noise supression using deep filtering 项目地址: https://gitcode.com/GitHub_Trending/de/DeepFilterNet 在远程通信、语音交互和音频处理领域&#xff0…...

5个实战技巧:轻松掌握RE-UE4SS脚本系统,解锁Unreal Engine游戏无限可能

5个实战技巧:轻松掌握RE-UE4SS脚本系统,解锁Unreal Engine游戏无限可能 【免费下载链接】RE-UE4SS Injectable LUA scripting system, SDK generator, live property editor and other dumping utilities for UE4/5 games 项目地址: https://gitcode.c…...

微服务可观测性实战:分布式链路追踪从入门到精通

前言微服务架构已经成了现代后端系统的主流选择。把一个单体应用拆成几十甚至上百个服务之后,每个服务的开发和部署确实灵活了,但排查问题变得异常困难——一个请求从网关进入,经过订单服务、库存服务、支付服务、积分服务,调用链…...

三步实现U盘自动备份:告别手动复制烦恼的智能解决方案

三步实现U盘自动备份:告别手动复制烦恼的智能解决方案 【免费下载链接】USBCopyer 😉 用于在插上U盘后自动按需复制该U盘的文件。”备份&偷U盘文件的神器”(写作USBCopyer,读作USBCopier) 项目地址: https://git…...

Marketch:如何用561行代码解决设计到开发的核心痛点

Marketch:如何用561行代码解决设计到开发的核心痛点 【免费下载链接】marketch Marketch is a Sketch 3 plug-in for automatically generating html page that can measure and get CSS styles on it. 项目地址: https://gitcode.com/gh_mirrors/ma/marketch …...

3步永久备份微信聊天记录:WeChatExporter让你的珍贵对话不再丢失

3步永久备份微信聊天记录:WeChatExporter让你的珍贵对话不再丢失 【免费下载链接】WeChatExporter 一个可以快速导出、查看你的微信聊天记录的工具 项目地址: https://gitcode.com/gh_mirrors/wec/WeChatExporter 你是否曾担心手机丢失或更换设备后&#xff…...

终极开源街机模拟器FinalBurn Neo:专业级复古游戏仿真技术深度解析

终极开源街机模拟器FinalBurn Neo:专业级复古游戏仿真技术深度解析 【免费下载链接】FBNeo FinalBurn Neo - We are Team FBNeo. 项目地址: https://gitcode.com/gh_mirrors/fb/FBNeo FinalBurn Neo(简称FBNeo)是一款功能强大的开源街…...

从开机问候到SIM卡菜单:一文读懂UICC CAT如何让SIM卡‘主动’起来

UICC CAT:解锁SIM卡主动交互能力的核心技术密码 还记得那些年手机开机时跳出的"中国移动欢迎您"吗?这个看似简单的问候背后,隐藏着一项被大多数人忽视的革命性技术——UICC CAT(卡应用工具包)。在物联网设备…...

JD晶导微Jingdao原厂原装一级代理分销经销

品牌 元件类别 型号 描述 包装 数量 JD 二极管 1N4007W SOD-123FL 3000 60,000...

终极指南:5分钟上手Translumo,Windows最强实时屏幕翻译神器

终极指南:5分钟上手Translumo,Windows最强实时屏幕翻译神器 【免费下载链接】Translumo Advanced real-time screen translator for games, hardcoded subtitles in videos, static text and etc. 项目地址: https://gitcode.com/gh_mirrors/tr/Transl…...

嵌入式视觉AI新纪元:ESP32摄像头集成与物联网视觉方案深度实践

嵌入式视觉AI新纪元:ESP32摄像头集成与物联网视觉方案深度实践 【免费下载链接】xiaozhi-esp32 An MCP-based chatbot | 一个基于MCP的聊天机器人 项目地址: https://gitcode.com/GitHub_Trending/xia/xiaozhi-esp32 在万物互联的时代,嵌入式视觉…...

3分钟上手:无需API的Instagram数据采集全攻略

3分钟上手:无需API的Instagram数据采集全攻略 【免费下载链接】instagram-crawler Get Instagram posts/profile/hashtag data without using Instagram API 项目地址: https://gitcode.com/gh_mirrors/in/instagram-crawler 你是否曾因Instagram API权限限制…...

终极Outfit字体完整指南:如何免费获得专业几何无衬线字体

终极Outfit字体完整指南:如何免费获得专业几何无衬线字体 【免费下载链接】Outfit-Fonts The most on-brand typeface 项目地址: https://gitcode.com/gh_mirrors/ou/Outfit-Fonts Outfit字体是一款专为品牌自动化设计的开源几何无衬线字体,提供从…...

华硕笔记本终极性能优化:G-Helper完整使用指南

华硕笔记本终极性能优化:G-Helper完整使用指南 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, Strix, Scar, and…...

实战避坑:为你的STM32MP157开发板手动编译和配置U-Boot SPL(附常见编译错误解决)

实战避坑:为你的STM32MP157开发板手动编译和配置U-Boot SPL(附常见编译错误解决) 嵌入式开发中,U-Boot SPL(Secondary Program Loader)作为系统启动的关键环节,往往成为开发者移植过程中的"…...

终极指南:30分钟搭建你的个人电视服务器 - Tvheadend实战部署全攻略

终极指南:30分钟搭建你的个人电视服务器 - Tvheadend实战部署全攻略 【免费下载链接】tvheadend Tvheadend is the leading TV streaming server for Linux with ATSC, DVB-C/C2, DVB-S/S2, DVB-T/T2, IPTV, SAT>IP and unix pipe input sources 项目地址: htt…...

CitySim高精度无人机轨迹数据集:智能交通安全研究的全面验证平台

CitySim高精度无人机轨迹数据集:智能交通安全研究的全面验证平台 【免费下载链接】UCF-SST-CitySim1-Dataset Official github page of UCF SST CitySim Dataset 项目地址: https://gitcode.com/gh_mirrors/ucf/UCF-SST-CitySim-Dataset CitySim是一个基于无…...

F3D三维查看器:如何快速预览3D模型而不必等待?

F3D三维查看器:如何快速预览3D模型而不必等待? 【免费下载链接】f3d Fast and minimalist 3D viewer. 项目地址: https://gitcode.com/GitHub_Trending/f3/f3d 您是否曾经因为打开一个3D模型文件而等待数分钟?是否在寻找一个既快速又功…...

从TensorFlow到BM1684:手把手教你将PyTorch模型部署到算能AI边缘盒子的完整流程

从TensorFlow到BM1684:手把手教你将PyTorch模型部署到算能AI边缘盒子的完整流程 在AI技术快速落地的今天,边缘计算正成为连接云端训练与终端应用的关键桥梁。算能AI边缘计算盒子凭借其10.6Tops的INT8算力和8核ARM Cortex-A53处理器,为开发者提…...

超融合数据库MatrixOne实战:统一HTAP、向量搜索与Git式数据管理

1. 从“数据孤岛”到“数据宇宙”:为什么我们需要一个超融合数据库?如果你在过去几年里负责过数据架构,大概率经历过这样的场景:业务初期,一个MySQL数据库就能搞定一切,简单又省心。但随着业务增长&#xf…...

MAI-UI:专为AI应用设计的React组件库,简化大模型对话界面开发

1. 项目概述:一个面向大模型应用的开源UI框架最近在折腾大模型应用开发的朋友,估计都遇到过类似的烦恼:模型接口调通了,业务逻辑也写好了,但一到构建用户界面(UI)这一步,就感觉特别费…...

机器学习中的解析解与数值解:理解算法选择本质

1. 机器学习中的解析解与数值解:为什么没有标准答案?作为一名从业多年的机器学习工程师,我经常被问到这样的问题:"我的数据应该用什么算法?"、"模型参数该怎么调?"。每当这时&#xff…...

Arduino OLED显示个性化中文:用自定义字体打造你的专属UI(从.ttf到.c文件全流程)

Arduino OLED显示个性化中文:从字体设计到UI定制的完整实践指南 在智能硬件项目中,OLED显示屏往往是人机交互的核心界面。当大多数开发者还在使用系统默认字体时,你是否想过为自己的Arduino项目注入独特的视觉个性?无论是复古风格…...

VOFA+不止能看波形:手把手教你打造专属直流电机PID调试上位机界面

从零构建直流电机PID调试神器:VOFA高级界面设计实战 调试直流电机PID参数时,你是否厌倦了反复烧录代码、查看波形的低效循环?传统调试方式如同蒙眼走钢丝——每次参数调整都伴随着漫长的编译等待和结果不确定性。本文将彻底改变这一局面&…...

当系统防护遇上逆向工程:探索VAC-Bypass-Loader的技术边界

当系统防护遇上逆向工程:探索VAC-Bypass-Loader的技术边界 【免费下载链接】VAC-Bypass-Loader Loader for VAC Bypass written in C. 项目地址: https://gitcode.com/gh_mirrors/va/VAC-Bypass-Loader 你是否曾想过,游戏反作弊系统背后的技术原理…...

多模型机器学习:超越集成学习的边界探索

1. 多模型机器学习入门指南在机器学习领域,我们常常听到"集成学习"这个术语,但很少有人深入探讨那些使用多个模型却又不完全符合集成学习定义的算法。作为一名从业多年的数据科学家,我发现很多同行对这些边界案例存在误解。本文将带…...

SAP MM | S4500 第五章——库存物料与消耗型物料采购

1. 单元概述与学习目标 作为 SAP 顾问,理解物料在系统中的“去向”是构建高效采购流程的基石。在 S/4HANA 中,采购业务根据物料是否进入库房管理,划分为库存采购与消耗型采购。本单元旨在通过深度对比这两者的业务流转,从底层逻辑上掌握 PR 到 PO 的转换以及后续的评估差异…...

Ubuntu 20.04上从源码编译Geth 1.10.5:避开Go版本不匹配的坑

Ubuntu 20.04源码编译Geth 1.10.5全流程指南:从环境准备到实战部署 在区块链开发领域,Geth作为以太坊网络的官方客户端实现,其源码编译能力是开发者必须掌握的核心技能。不同于简单的apt-get安装,源码编译不仅能让你获得最新功能&…...

开源硬件改造卡西欧F-91W:传感器扩展与极致能效实践

1. 项目概述:用开源硬件改造经典卡西欧手表 卡西欧F-91W这款1989年问世的电子表堪称工业设计史上的奇迹——它售价仅15美元却拥有惊人的可靠性,三十多年来外观几乎未变,至今仍在全球畅销。但正是这种经典设计激发了"Oddly Specific Obje…...