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

Go语言泛型基础

泛型

Go 并不是一种静止的、一成不变的编程语言。新的功能是在经过大量的讨论和实验后慢慢采用的。最初的 Go1.0发布以来,Go语言习惯的模式已经发生了重大变化1.7的context、1.11的modules、1.13 error嵌套等Go的 1.18 版本包括了类型参数的实现,也就是俗称的泛型泛型虽然很受期待,但实际上推荐的使用场景也并没有那么广泛。但是我们作为学习者,一定要了解学会,遇到了至少不懵逼!

package mainimport "fmt"func main() {stars := []string{"wk", "ce"}printArray(stars)is := []int{1, 2}printArray(is)
}// **我们不限定他类型,让调用者自己去定义类型。T ** <>// []T 形式类型实际类型
/*
**内置的泛型类型any和comparable**
**any:** 表示go里面所有的内置基本类型,等价于 interface}
**comparable:** 表示go里面所有内置的可比较类型:int、uint、float、bool、struct、指针'等一切可以比较的类型
*/
func printArray[T string | int](arr []T) {for _, a := range arr {fmt.Println(a)}
}
小结:泛型的作用
  • 泛型减少重复代码并提高类型安全性。
  • 使用场景:当你需要针对不同类型书写相同逻辑时,使用泛型来简化代码是最好的处理方法。

泛型类型

观察下面这个简单的例子:

type s1 []int
var a sl = []int{123} // 正确
var b s1 = []float321.02.03,0} //  错误,因为Intslice的底层类型是[]int,浮点类型的切片无法赋值

这里定义了一个新的类型IntSlice,它的底层类型是 int,理所当然只有int类型的切片能赋值给 ntSlice 类型的变量。

接下来如果我们想要定义一个可以容纳 loat32 或 string 等其他类型的切片的话该怎么办?很简单,给每种类型都定义个新类型

type sl []int
type s2 []float32
type s3 []float643

go但是这样做的问题显而易见,它们结构都是一样的只是成员类型不同就需要重新定义这么多新类型。那么有没有一个办法能只定义一个类型就能代表上面这所有的类型呢?答案是可以的,这时候就需要用到泛型了:

type slice[T int|float32lfloat64] []T
  • 不同于一般的类型定义,这里类型名称 Slice 后带了中括号,对各个部分做一个解说就是
  • T就是上面介绍过的类型形参(Type parameter),在定义Slice类型的时候T代表的具体类型并不确定,类似一个占位符
  • int float32 float64 这部分被称为类型约束(Type constraint),中间的 的意思是告诉编译器,类型形参T只可以接收 int 或 float32或float64这三种类型的实参
  • 中括号里的 Tint float32 flat64 这一整串因为定义了所有的类型形参(在这个例子里只有一个类型形参T),所以我们称其为 类型形参列表(type parameter list)
  • 这里新定义的类型名称叫 slice[T]

这种类型定义的方式中带了类型形参,很明显和普通的类型定义非常不一样,所以我们将这种类型定义中带 类型形参 的类型,称之为 泛型类型

package mainimport "fmt"func main() {//定义一个泛型类型切片type Slice[T int | float64 | float32] []Tvar a Slice[int] = []int{1, 2, 3}fmt.Println(a)fmt.Printf("%T", a)var b Slice[float32] = []float32{1, 2, 3}fmt.Println(b)fmt.Printf("%T", b)var c Slice[float64] = []float64{1, 2, 3}fmt.Println(c)fmt.Printf("%T", c)//定义一个泛型类型maptype myMap[KEY int | string, VALUE any] map[KEY]VALUEvar m1 myMap[string, any] = map[string]any{"go":   9.9,"java": 9.0,}fmt.Println(m1)
}

所有类型定义都可使用类型形参,所以下面这种结构体以及接口的定义也可以使用类型形参:

// 一个泛型类型的结构体。可用 int 或 sring 类型实例化
type MyStruct[T int | string] struct {Id T 1 "uuid"Name string
}
// 一个泛型接口
type IPrintData[T int | float32 | string] interface {Print(data T)
}
// 一个泛型通道,可用类型实参 int 或 string 实例化
type MyChan[T int | string] chan T

特殊的泛型类型

这里讨论种比较特殊的泛型类型,如下

type wow[T int | string] int
var a wow[int] = 1233// 编译正确
var b wow[string] = 123 // 编译正确
var c Wow[string] ="he11o” // 编译错误,因为"he11o"不能赋值给底层类型int

这里虽然使用了类型形参,但因为类型定义是 type wow[Tint|string] int ,所以无论传入什么类型实参,实例化后的新类型的底层类型都是int。所以int类型的数字123可以赋值给变量a和b,但string类型的字符串“hello”不能赋值给c
这个例子没有什么具体意义,但是可以让我们理解泛型类型的实例化的机制

泛型函数

package mainimport "fmt"type MySlice[T int | float64] []T// Sum 给泛型添加方法
func (s MySlice[T]) Sum() T {var sum Tfor _, v := range s {sum += v}return sum
}// Add 泛型函数
func Add[T int | float64 | string](a T, b T) T {return a + b
}func main() {var s MySlice[int] = []int{1, 2, 3, 4, 5}fmt.Println(s.Sum())var f MySlice[float64] = []float64{1.0, 2.1, 3.2, 4.3, 5.7}fmt.Println(f.Sum())fmt.Println(Add(1, 2))fmt.Println(Add(1.2, 2.3))fmt.Println(Add("3333", "4444"))
}

自定义泛型类型

package mainimport "fmt"// MyInt 自定义泛型约束
type MyInt interface {int | int8 | int16 | int32 | int64
}func GetMaxNum[T MyInt](a, b T) T {if a > b {return a}return b
}func main() {fmt.Println(GetMaxNum(10, 20))
}

相关文章:

Go语言泛型基础

泛型 Go 并不是一种静止的、一成不变的编程语言。新的功能是在经过大量的讨论和实验后慢慢采用的。最初的 Go1.0发布以来&#xff0c;Go语言习惯的模式已经发生了重大变化1.7的context、1.11的modules、1.13 error嵌套等Go的 1.18 版本包括了类型参数的实现&#xff0c;也就是…...

基于android的中医养生app

需求信息&#xff1a; 中医健康养生APP分为四大模块&#xff0c;其中个人中心又分为4大块&#xff0c;游客用户个人中心是空白的。 上图为养生知识推广普及模块的功能结构图。 在养生知识推广普及模块界面&#xff0c;用户可以选择自己感兴趣的模块进行文章浏览&#xff0c;文章…...

2023美赛C代码思路结果【全部更新完毕】注释详尽

C题已完成全部代码&#xff0c;注释详尽&#xff0c;并增加扰动项&#xff0c;保证大家的结果不会撞 需要全部问题的可以点击&#xff1a;https://www.jdmm.cc/file/2708697/ 下面贴出核心代码&#xff1a; -- coding: utf-8 -- TODO: 入口函数 import numpy as np from…...

实现8086虚拟机(二)——模拟CPU和内存

文章目录CPU 架构EU&#xff08;执行单元&#xff09;BIU&#xff08;总线接口单元&#xff09;小结一下模拟内存模拟 BIU模拟 EU模拟 CPU总结要模拟 8086 CPU 运行&#xff0c;必须知道 CPU 的一些知识。下文的知识点都来自《Intel_8086_Family_Users_Manual 》。CPU 架构 微…...

Windows7下使用VMware11.1.1安装ubuntu-16.04.7

一、说明二、安装说明三、安装步骤详解1、先安装VMware软件2、创建虚拟机3、编辑虚拟机4、开启虚拟机&#xff0c;初始化Linux系统一、说明 虽然VMware和ubuntu最新版已经很高了&#xff0c;我这电脑由于是win7配值还低&#xff0c;所以采用低版本来安装 VMware版本&#xff1…...

基于SSM框架的CMS内容管理系统的设计与实现

基于SSM框架的CMS内容管理系统的设计与实现 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目…...

华为OD机试 - 运动会 | 机试题算法思路 【2023】

最近更新的博客 华为OD机试 - 自动曝光(Python) | 机试题算法思路 【2023】 华为OD机试 - 双十一(Python) | 机试题算法思路 【2023】 华为OD机试 - 删除最少字符(Python) | 机试题算法思路 【2023-02】 华为OD机试 - Excel 单元格数值统计(Python) | 机试题算法思路 …...

(C语言篇)扫雷的实现

文章目录 一、开始时的基本思维&#xff1a;二、进入游戏的逻辑(test.c文件中实现)三、游戏的编写 1. 初始化棋盘 I. test.cII. game.hIII. game.c 2.打印棋盘 I. test.cII. game.hIII. game.c 3.布置雷 I. test.cII. game.hIII. game.c 4.排查雷 I. test.cII. game.hIII. gam…...

华为手表开发:WATCH 3 Pro(8)获取位置服务

华为手表开发&#xff1a;WATCH 3 Pro&#xff08;8&#xff09;获取位置服务初环境与设备文件夹&#xff1a;文件新增第二页面geolocation.hmlgeolocation.js修改首页 -> 新建按钮 “ 跳转 ”index.hmlindex.js 引用包&#xff1a;system.router首页效果点击结果按钮跳转后…...

AnLogicFPGA设计的时序约束及时序收敛

本篇博文讲了三个内容&#xff1a;时序约束基本概念、时序约束命令、时序收敛技巧 时序约束基本概念 时序设计的实质就是满足每一个触发器的建立&#xff08;setup&#xff09;时间和保持&#xff08;hold&#xff09;时间。 建立时间(Tsu) 触发器的时钟信号沿到来以前&…...

ubuntu22.10安装sogou输入法后不能输入中文字符(可以输入中文标点符号)

问题描述 想在ubuntu22.10系统上安装sogou中文输入法&#xff0c;按照sogou输入法网站给出的步骤安装后&#xff0c;发现无法输入中文字符&#xff0c;但是可以输入中文标点符号。 sogou网站&#xff1a;https://shurufa.sogou.com/linux/guide 寻找答案1 通过各种百度和必…...

基于微信小程序的生活日用品交易平台 的设计与实现

基于微信小程序的生活日用品交易平台 的设计与实现 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一…...

15:高级篇 - CTK 事件与监听

作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 生命周期层事件 在 Plugin 生命周期的不同状态相互转换时,CTK Plugin Framework 会发出各种不同的事件,以供事先注册好的事件监听器处理,这些事件被称为“生命周期层事件”。CTK Plugin Framework 支持的…...

SpringBoot Notes

文章目录1 SpringBootWeb快速入门1.1Spring官网1.2 Web分析2. HTTP协议2.1 HTTP介绍34 SpringBootWeb请求响应5 响应6 分层解耦6.1 三层架构6.1.1 三层架构介绍6.1.2 基于三层架构的程序执行流程&#xff1a;6.1.3 代码拆分6.2 分层解耦6.2.1 内聚、耦合6.2.2 解耦思路6.3 IOC&…...

CoreDNS

目录 文章目录目录本节实战前言1、环境变量2、DNS1.DNS 解析过程2.根域名服务器3.顶级域名服务器4.权威性域名服务器5.dig 域名3、CoreDNS1.CoreDNS 扩展配置&#xff08;1&#xff09;开开启日志服务&#xff08;2&#xff09;特定域名使用自定义 DNS 服务器&#xff08;3&…...

码农饭碗不保——ChatGPT正在取代Coder

码农饭碗不保——ChatGPT正在取代Coder 最近被OpenAI的ChatGPT刷屏了。我猜你已经读了很多关于ChatGPT的文章&#xff0c;不需要再介绍了。假如碰巧您还不太了解ChatGPT是什么&#xff0c;可以先看一下这篇文章&#xff0c;然后再回来继续。 与ChatGPT对话很有趣&#xff0c;…...

PAT (Advanced Level) Practice 1004 Counting Leaves

1004 Counting Leaves题目翻译代码分数 30 作者 CHEN, Yue 单位 浙江大学 A family hierarchy is usually presented by a pedigree tree. Your job is to count those family members who have no child. Input Specification: Each input file contains one test case. Eac…...

基于Redis实现的分布式锁

基于Redis实现的分布式锁什么是分布式锁分布式锁主流的实现方案Redis分布式锁Redis分布式锁的Java代码体现优化一&#xff1a;使用UUID防止误删除优化二&#xff1a;LUA保证删除原子性什么是分布式锁 单体单机部署中可以为一个操作加上锁&#xff0c;这样其他操作就会等待锁释…...

2023年,还找算法岗工作吗?

点击下方卡片&#xff0c;关注“CVer”公众号AI/CV重磅干货&#xff0c;第一时间送达2023年春招&#xff08;补招&#xff09;已经大规模启动了&#xff01;距离2023年暑期实习不到2个月&#xff01;距离2024届校招提前批不到4个月&#xff01;距离2024届秋招正式批不到6个月&a…...

正点原子ARM裸机开发篇

裸机就是手动的操作硬件来实现驱动设备&#xff0c;后面会有驱动框架不需要这么麻烦 第八章 汇编 LED 灯实验 核心过程 通过汇编语言来控制硬件&#xff08;驱动程序&#xff09; 代码流程 1、使能 GPIO1 时钟 GPIO1 的时钟由 CCM_CCGR1 的 bit27 和 bit26 这两个位控制&…...

篇章一 论坛系统——前置知识

目录 1.软件开发 1.1 软件的生命周期 1.2 面向对象 1.3 CS、BS架构 1.CS架构​编辑 2.BS架构 1.4 软件需求 1.需求分类 2.需求获取 1.5 需求分析 1. 工作内容 1.6 面向对象分析 1.OOA的任务 2.统一建模语言UML 3. 用例模型 3.1 用例图的元素 3.2 建立用例模型 …...

持续交付的进化:从DevOps到AI驱动的IT新动能

文章目录 一、持续交付的本质&#xff1a;从手动到自动的交付飞跃关键特性案例&#xff1a;电商平台的高效部署 二、持续交付的演进&#xff1a;从CI到AI驱动的未来发展历程 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/101f72defaf3493ba0ba376bf09367a2.png)中国…...

记一次spark在docker本地启动报错

1&#xff0c;背景 在docker中部署spark服务和调用spark服务的微服务&#xff0c;微服务之间通过fegin调用 2&#xff0c;问题&#xff0c;docker容器中服务器来后&#xff0c;注册中心都有&#xff0c;调用服务也正常&#xff0c;但是调用spark启动任务后报错&#xff0c;报错…...

【见合八方平面波导外腔激光器专题系列】用于干涉光纤传感的低噪声平面波导外腔激光器2

----翻译自Mazin Alalus等人的文章 摘要 1550 nm DWDM 平面波导外腔激光器具有低相位/频率噪声、窄线宽和低 RIN 等特点。该腔体包括一个半导体增益芯片和一个带布拉格光栅的平面光波电路波导&#xff0c;采用 14 引脚蝶形封装。这种平面波导外腔激光器设计用于在振动和恶劣的…...

MAZANOKE结合内网穿透技术实现跨地域图像优化服务的远程访问过程

文章目录 前言1. 关于MAZANOKE2. Docker部署3. 简单使用MAZANOKE4. 安装cpolar内网穿透5. 配置公网地址6. 配置固定公网地址总结 前言 在数字世界高速发展的今天&#xff0c;您是否察觉到那些静默增长的视觉数据正在悄然蚕食存储空间&#xff1f;随着影像记录成为日常习惯&…...

软件测试—学习Day11

今天学习下兼容性 1.App兼容性常见问题 以下是关于 App 兼容性问题的常见举例&#xff0c;涵盖界面展示、操作逻辑、性能差异三大维度&#xff0c;涉及不同系统、设备及网络环境的兼容性场景&#xff1a; 一、界面展示问题 界面展示兼容性问题主要由操作系统版本差异、屏幕…...

Kaggle-Predicting Optimal Fertilizers-(多分类+xgboost+同一特征值多样性)

Predicting Optimal Fertilizers 题意&#xff1a; 给出土壤的特性&#xff0c;预测出3种最佳的肥料 数据处理&#xff1a; 1.有数字型和类别型&#xff0c;类别不能随意换成数字&#xff0c;独热编码。cat可以直接处理category类型。 2.构造一些相关土壤特性特征 3.由于la…...

Redis持久化策略:RDB与AOF详解

目录 1. RDB持久化工作原理触发机制优点缺点配置示例 2. AOF持久化工作原理同步策略重写机制优点缺点配置示例 3. RDB与AOF比较4. 混合持久化(Redis 4.0)5. 选择建议 Redis提供了两种主要的持久化机制来保证数据安全&#xff1a;RDB(Redis Database)和AOF(Append Only File)。本…...

【学习笔记】深入理解Java虚拟机学习笔记——第3章 垃圾收集器与内存分配策略

第3章 垃圾收集器与内存分配策略 3.1 概述 略 3.2 对象已死&#xff1f; “死去”即不可能以任何途径访问到 3.2.1 引用计数算法 每个对象维护一个计数器&#xff0c;引用即加1&#xff0c;引用失效便减1。 3.2.2 可达性分析算法&#xff08;主流&#xff09; 即根据GC…...

MCP(Model Context Protocol)与提示词撰写

随着大模型&#xff08;LLM&#xff09;在复杂任务中的普及&#xff0c;如何让模型高效调用外部工具和数据成为关键挑战。传统函数调用&#xff08;Function Calling&#xff09;依赖开发者手动封装 API&#xff0c;而 MCP&#xff08;Model Context Protocol&#xff09; 通过…...