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

Go 语言 UUID 库 google/uuid 源码解析:UUID version4 的实现

google/uuid 库地址

本文将解析 googl/uuid 库中 UUID 变体10版本4的实现。

版本 4 的 UUID 采取完全随机的方式实现,简单来说就是将 UUID 中的 122 位全部随机填充(剩余的 6 位作标记位)。版本 4 的 UUID 存在一定的重复风险,但就如源码注释中所说:“一年内创建几十万亿个 UUID 并出现一个重复的概率,就如同一个人一年被流星击中的风险一样(估计为 170 亿分之一)”

UUID 版本4 的实现代码写在 version4 中,提供了两种不同的实现方式,一种是直接通过随机生成器 io.Reader 生成,另一种则是通过随机池生成。

无随机池生成(随机生成器直接生成)

这种生成方法定义在 NewRandomFromReader 中,NewRandomFromReader 接收 io.Reader 作为参数,并返回 UUID 和 error。其代码很简单:

// NewRandomFromReader 根据从给定 io.Reader 读取的字节返回一个 UUID。
func NewRandomFromReader(r io.Reader) (UUID, error) {var uuid UUID_, err := io.ReadFull(r, uuid[:])if err != nil {return Nil, err}uuid[6] = (uuid[6] & 0x0f) | 0x40 // 版本 4uuid[8] = (uuid[8] & 0x3f) | 0x80 // 变体为 10return uuid, nil
}

可以拆解为两部分,一部分随机填充 UUID,另一部分标志版本和变体。

随机填充最关键的部分便是 io.Reader 和 io.ReadFull。

Reader 是定义在 io 包中的接口,是所有输入操作的基础,它是读取数据行为的抽象。在 Reader 接口中存在一个 Read 方法,会将读取到的是数据输出到字节切片 p 中:

type Reader interface {Read(p []byte) (n int, err error)
}

任何实现了 Read 方法的对象都可以视为一个 Reader。

而 NewRandomFromReader 函数由另一个内部函数调用,使用的是 rand.Reader 即定义在 rand.go 中的 Reader,其 “Reader 是一个全局的,共享的密码学安全随机数生成器实例。”(go 源码注释)

而 io.ReadFull 是一个辅助函数,用于辅助 io.Read 将切片填满。

所以 _, err := io.ReadFull(r, uuid[:]) 的含义便是使用密码学安全的随机数填满切片 uuid(16 字节的切片)。

而标识部分可以查看此篇文章Go 语言 UUID 库 google/uuid 源码解析:UUID version1 的实现的 分割时间信息 的末尾。

随机池生成

这种生成方法定义在 newRandomFromPool 中 代码如下:

func newRandomFromPool() (UUID, error) {var uuid UUIDpoolMu.Lock()if poolPos == randPoolSize {_, err := io.ReadFull(rander, pool[:])if err != nil {poolMu.Unlock()return Nil, err}poolPos = 0}copy(uuid[:], pool[poolPos:(poolPos+16)])poolPos += 16poolMu.Unlock()uuid[6] = (uuid[6] & 0x0f) | 0x40 // 版本 4uuid[8] = (uuid[8] & 0x3f) | 0x80 // 变体为 10return uuid, nil
}

可以也拆解为两部分,一部分从随机池读取 UUID,另一部分标志版本和变体。

从随机池读取 UUID 的原理就是预设一个随机池并预填充数据,当需要数据时,便从随机池中截取数据。而随机池也是一个切片 pool = [randPoolSize]byte,而 randPoolSize 则硬编码为 16 * 16,所以随机池其实是一个 16 * 16 字节的切片。与 pool 配合使用的还有 poolMupoolPos,poolMu 用于避免并访问随机池切片,而 poolPos 则是用于指定当前 UUID 的切片范围,每次生成 UUID 时即从随机池中拷贝 poolPospoolPos + 16 的数据(copy(uuid[:], pool[poolPos:(poolPos+16)])),然后 poolPos += 16 更改下次 UUID 的范围来避免获取到相同的数据。如果判断到已经到达随机池的上限了,则使用 io.ReadFull 重新填充随机池。

if poolPos == randPoolSize {_, err := io.ReadFull(rander, pool[:])if err != nil {poolMu.Unlock()return Nil, err}poolPos = 0
}

值得一提的是 poolPos 在定义的时候便是 poolPos = randPoolSize,所以在第一次生成 UUID 的时候便是随机池第一次被填充的时候。

如何决定什么时候使用随机池

对于 version4 还有个重要的参数就是布尔类型的 poolEnabledpoolEnabled 用于指定是否使用随机池,其默认值为 false,其搭配使用的是 EnableRandPoolDisableRandPool,分别用于启动缓冲池和关闭缓冲池,其实现逻辑简单说就是将 poolEnabled 设置为 truefalse

而利用到 poolEnabled 的是函数 NewRandom

func NewRandom() (UUID, error) {if !poolEnabled {return NewRandomFromReader(rander)}return newRandomFromPool()
}

poolEnabledtrue 则调用 newRandomFromPool,否则调用NewRandomFromReader

NewRandom 再往上层封装便是用户接口 New 了:

func New() UUID {return Must(NewRandom())
}

此处的 Must 用处便是检查 NewRandow 是否返回了 error。

到这里一个完整的 UUID 版本4便完成了。

以上就是 UUID 版本4实现的所有内容,希望你能有所收获。

相关文章:

Go 语言 UUID 库 google/uuid 源码解析:UUID version4 的实现

google/uuid 库地址 本文将解析 googl/uuid 库中 UUID 变体10版本4的实现。 版本 4 的 UUID 采取完全随机的方式实现,简单来说就是将 UUID 中的 122 位全部随机填充(剩余的 6 位作标记位)。版本 4 的 UUID 存在一定的重复风险,但…...

开发个人Go-ChatGPT--6 OpenUI

开发个人Go-ChatGPT–6 OpenUI Open-webui Open WebUI 是一种可扩展、功能丰富且用户友好的自托管 WebUI,旨在完全离线运行。它支持各种 LLM 运行器,包括 Ollama 和 OpenAI 兼容的 API。 功能 由于总所周知的原由,OpenAI 的接口需要密钥才…...

Spring中的工厂模式详解及应用示例

1. Spring中的BeanFactory BeanFactory是一个接口,表示它是一个工厂,负责生产和管理bean。在Spring中,BeanFactory是IOC容器的核心接口,定义了管理Bean的通用方法,如 getBean 和 containsBean。 BeanFactory与IOC容器…...

Electron 简单搭建项目

准备工作 全局安装 node npm创建文件夹,并执行 npm init安装 electron npm i electron --save-dev在 package.json 配置文件中的scripts字段下增加一条start命令: {"scripts": {"start": "electron ."} }由于配置中的入…...

旗晟智能巡检机器人:开启工业运维的智能化新篇章

在当今快速发展的工业领域,安全、效率和成本控制是企业运营的核心。旗晟科技以创新为驱动,推出了一站式的工业级智能巡检机器人数字化全景运维解决方案,为石油、天然气、化工、电力等高危行业提供了一个全新的运维模式。 一、面对挑战&#x…...

vue3的常用 Composition API有哪些?

Vue.js 3.0 引入了 Composition API,作为一种新的组织组件逻辑的方式,相比于传统的 Options API,Composition API 提供了更灵活、更可复用的代码组织方式。 以下是 Vue 3.0 中常用的 Composition API:setup() 函数: s…...

深度优先算法-DFS(算法篇)

算法之深度优先算法 深度优先算法(DFS) 概念: 深度优先算法(DFS)跟BFS算法一样是用于遍历图的算法,但是DFS并不像BFS算法一样,它搜索出来的路径不具有最短性,并且dfs算法类似于枚举,因此DFS算法一般用于求出问题的所…...

C++模块化之内部类

目录 1.引言 2.内部类的访问控制 3.优缺点分析 4.实际运用 4.1.实现复杂数据结构 4.2.封装细节实现 4.3.事件处理和回调 4.4.模板元编程辅助类 4.5. 访问控制和封装 4.6. 代码组织和模块化 5.总结 1.引言 在C中,内部类(Nested Class&#xff…...

k8s-第九节-命名空间

命名空间 如果一个集群中部署了多个应用,所有应用都在一起,就不太好管理,也可以导致名字冲突等。 我们可以使用 namespace 把应用划分到不同的命名空间,跟代码里的 namespace 是一个概念,只是为了划分空间。 # 创建命…...

【AI大模型新型智算中心技术体系深度分析 2024】

文末有福利! ChatGPT 系 列 大 模 型 的 发 布, 不 仅 引 爆 全 球 科 技 圈, 更 加 夯 实 了 人 工 智 能(Artificial Intelligence, AI)在未来改变人类生产生活方式、引发社会文明和竞争力代际跃迁的战略性地位。当…...

王道计算机数据结构+插入排序、冒泡排序、希尔排序、快速排序、简单选择排序

本内容是基于王道计算机数据结构的插入排序、冒泡排序、希尔排序、快速排序、简单选择排序整理。 文章目录 插入排序算法性能代码 冒泡排序算法性能代码 希尔排序算法性能代码 快速排序算法性能代码 简单选择排序算法性能代码 插入排序 算法 算法思想:每次将一个…...

python爬虫学习(三十三天)---多线程上篇

hello,小伙伴们!我是喔的嘛呀。今天我们来学习多线程方面的知识。 目录 一、了解多线程 (1)大概描述 (2)多线程爬虫的优势 (3)多线程爬虫的实现方式 (4&#xff09…...

JavaScript 原型链那些事

在讲原型之前我们先来了解一下函数。 在JS中,函数的本质就是对象,它与其他对象不同的是,创建它的构造函数与创建其他对象的构造函数不一样。那产生函数对象的构造函数是什么呢?是一个叫做Function的特殊函数,通过newFu…...

nginx的知识面试易考点

Nginx概念 Nginx 是一个高性能的 HTTP 和反向代理服务。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好。 Nginx 专为性能优化而开发,性能是其最重要的考量指标,实现上非常注重效率&#…...

每日Attention学习9——Efficient Channel Attention

模块出处 [CVPR 20] [link] [code] ECA-Net: Efficient Channel Attention for Deep Convolutional Neural Networks 模块名称 Efficient Channel Attention (ECA) 模块作用 通道注意力 模块结构 模块代码 import torch import torch.nn as nn import torch.nn.functional …...

Java语言程序设计——篇三(1)

选择结构 概述选择单分支if语句例题讲解 双分支if-else语句例题讲解 条件运算符多分支的if-else语句例题讲解 嵌套的if语句例题讲解 switch语句结构例题讲解代码演示运行结果 概述 Java中的控制结构,包括: 1、选择结构( if、if-else、switch ) 2、循环结…...

基于SpringBoot实现轻量级的动态定时任务调度

在使用SpringBoot框架进行开发时,一般都是通过Scheduled注解进行定时任务的开发: Component public class TestTask {Scheduled(cron"0/5 * * * * ? ") //每5秒执行一次public void execute(){SimpleDateFormat df new SimpleDateFormat(…...

夸克升级“超级搜索框” 推出AI搜索为中心的一站式AI服务

大模型时代,生成式AI如何革新搜索产品?阿里智能信息事业群旗下夸克“举手答题”。7月10日,夸克升级“超级搜索框”,推出以AI搜索为中心的一站式AI服务,为用户提供从检索、创作、总结,到编辑、存储、分享的一…...

element-ui el-select选择器组件下拉框增加自定义按钮

element-ui el-select选择器组件下拉框增加自定义按钮 先看效果 原理&#xff1a;在el-select下添加禁用的el-option&#xff0c;将其value绑定为undefined&#xff0c;然后覆盖el-option禁用状态下的默认样式即可 示例代码如下&#xff1a; <template><div class…...

Python基于you-get下载网页上的视频

​ 1.python 下载地址 下载 : https://www.python.org/downloads/ 2. 配置环境变量 配置 python_home 地址 配置 python_scripts 地址 在path 中加入对应配置 3. 验证 ​ C:\Users>python --version Python 3.12.4C:\Users>wheel version wheel 0.43.04. 下载 c…...

Python跑在浏览器里?揭秘2024最稳WASM部署方案:3大框架实测对比+性能压测数据

第一章&#xff1a;Python跑在浏览器里&#xff1f;揭秘2024最稳WASM部署方案&#xff1a;3大框架实测对比性能压测数据Python 从未真正“离开服务器”&#xff0c;但 2024 年&#xff0c;它已能以接近原生的速度在浏览器中执行——依托 WebAssembly&#xff08;WASM&#xff0…...

为什么你的Flask农业API总在灌溉高峰期崩?Python高并发部署的4层熔断架构设计(实测QPS提升6.8倍)

第一章&#xff1a;为什么你的Flask农业API总在灌溉高峰期崩&#xff1f;Python高并发部署的4层熔断架构设计&#xff08;实测QPS提升6.8倍&#xff09; 当全省智能灌溉系统在每日清晨5:00–7:00集中调度水阀、上传土壤墒情数据时&#xff0c;基于默认配置的Flask API常出现进程…...

手把手教你用kafka-storage.sh重新格式化Kafka KRaft集群数据目录(解决No meta.properties报错)

深入解析Kafka KRaft模式下数据目录重构与集群恢复实战指南 当你在深夜收到Kafka集群告警&#xff0c;发现所有节点因No meta.properties报错而集体罢工时&#xff0c;那种头皮发麻的感觉我太熟悉了。去年双十一大促前夜&#xff0c;我们因为临时调整存储路径而遭遇类似问题&am…...

FireRedASR-AED-L在Windows系统的部署问题解决方案

FireRedASR-AED-L在Windows系统的部署问题解决方案 1. 引言 如果你正在Windows系统上尝试部署FireRedASR-AED-L这个强大的语音识别模型&#xff0c;可能会遇到各种让人头疼的问题。环境配置、依赖冲突、GPU兼容性——这些都是Windows环境下部署深度学习模型时常见的拦路虎。 …...

避坑指南:关系数据库设计中90%人会犯的完整性约束错误(附真实案例)

避坑指南&#xff1a;关系数据库设计中90%人会犯的完整性约束错误&#xff08;附真实案例&#xff09; 在电商大促期间&#xff0c;某平台突然出现大量"幽灵订单"——用户支付成功后订单消失&#xff0c;而库存却异常扣减。技术团队紧急排查发现&#xff0c;问题根源…...

staticFunctional:嵌入式零堆内存的std::function替代方案

1. staticFunctional&#xff1a;嵌入式系统中零动态内存开销的 std::function 替代方案1.1 设计动因与工程痛点在资源受限的嵌入式系统&#xff08;如 ARM Cortex-M0/M4、AVR、ESP32、Teensy 系列&#xff09;中&#xff0c;std::function的标准实现存在根本性兼容障碍。其典型…...

个人记账自动化:OpenClaw+nanobot解析消费短信

个人记账自动化&#xff1a;OpenClawnanobot解析消费短信 1. 为什么需要自动化记账 每个月末看着银行卡余额叹气时&#xff0c;我总在想&#xff1a;钱到底花哪儿了&#xff1f;手动记账App试过七八个&#xff0c;最终都败给"忘记记录"这个人类通病。直到发现消费短…...

百度网盘提取码智能获取工具:让资源下载效率提升100倍的秘密武器

百度网盘提取码智能获取工具&#xff1a;让资源下载效率提升100倍的秘密武器 【免费下载链接】baidupankey 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 还在为获取百度网盘分享链接的提取码而浪费宝贵时间吗&#xff1f;面对"请输入提取码"的…...

Cocos解耦移动和发射模块

目标&#xff1a;玩家受到摇杆A控制移动和方向&#xff0c;发射受到摇杆B负责方向和发射 //玩家模块 ccclass(Player) export class Player extends Component {//玩家速度Speed:number 500;//玩家方向property(Vec3)PlayerDir:Vec3;//虚拟摇杆property(Node)Joystick:Node n…...

从收音机到Wi-Fi:手把手复现经典小信号调谐放大器实验(附Multisim仿真文件)

从矿石收音机到5G射频前端&#xff1a;调谐放大器技术演进与Multisim仿真实践 上世纪二十年代&#xff0c;当业余无线电爱好者们用矿石和线圈组装出最简单的接收装置时&#xff0c;他们可能不会想到&#xff0c;这种基于LC谐振原理的选频技术会延续百年&#xff0c;成为现代无线…...