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

02.Golang 切片(slice)源码分析(一、定义与基础操作实现)

Golang 切片(slice)源码分析(一、定义与基础操作实现)

注意当前go版本代码为1.23

一、定义

slice 的底层数据是数组,slice 是对数组的封装,它描述一个数组的片段。两者都可以通过下标来访问单个元素。

数组是定长的,长度定义好之后,不能再更改。在 Go 中,数组是不常见的,因为其长度是类型的一部分,限制了它的表达能力,比如 [3]int 和 [4]int 就是不同的类型。

而切片则非常灵活,它可以动态地扩容。切片的类型和长度无关。

数组就是一片连续的内存, slice 实际上是一个结构体,包含三个字段:长度、容量、底层数组。

type slice struct {array unsafe.Pointerlen   intcap   int
}

数据结构如下:

切片数据结构

注意,底层数组是可以被多个 slice 同时指向的,因此对一个 slice 的元素进行操作是有可能影响到其他 slice 的。

二、操作

2.1创建

src/runtime/slice.go 主要逻辑就是基于容量申请内存。

func makeslice(et *_type, len, cap int) unsafe.Pointer {// 计算切片所需的内存大小,cap 为切片容量,et.Size_ 为每个元素的大小// math.MulUintptr 执行无符号整数乘法,并返回结果和一个表示是否发生溢出的布尔值mem, overflow := math.MulUintptr(et.Size_, uintptr(cap))// 检查以下几种错误情况:// 1. overflow:容量计算时发生溢出// 2. mem > maxAlloc:所需的内存超过最大可分配内存// 3. len < 0:切片长度为负数// 4. len > cap:切片长度大于容量if overflow || mem > maxAlloc || len < 0 || len > cap {// 注意:当用户执行 make([]T, bignumber) 时,产生 "len out of range" 错误,而不是 "cap out of range" 错误。// 虽然 "cap out of range" 也是对的,但由于容量是隐式提供的,因此提示长度错误更清晰。// 参考:golang.org/issue/4085// 重新计算基于长度的内存大小,以便在容量溢出时提供更准确的错误信息(例如 len 也溢出)mem, overflow := math.MulUintptr(et.Size_, uintptr(len))// 再次检查溢出、内存超出限制以及长度为负数的情况if overflow || mem > maxAlloc || len < 0 {panicmakeslicelen() // 长度错误,触发 panic}panicmakeslicecap() // 容量错误,触发 panic}// 调用 mallocgc 分配内存。// mallocgc 是 Go 运行时中的函数,用于分配内存并在垃圾回收器中注册该内存。// 参数://   mem: 要分配的内存大小//   et: 切片元素的类型//   true: 指示分配的内存应该被清零return mallocgc(mem, et, true)
}

2.2扩容

核心源码 growslice-》nextslicecap&&roundupsize

首先通过nextslicecap计算出一个初步的扩容值,通过roundupsize内存对齐得出最终的扩容值,并不是网上的简单公式。

在1.18版本之前,slice源码中nextslicecap扩容主要逻辑为:

当原 slice 容量小于 1024 的时候,新 slice 容量变成原来的 2 倍;原 slice 容量超过 1024,新 slice 容量变成原来的1.25倍。

在1.18版本更新之后,slice源码中nextslicecap的扩容主要逻辑变为了:

当原slice容量(oldcap)小于256的时候,新slice(newcap)容量为原来的2倍;原slice容量超过256,新slice容量newcap = oldcap+(oldcap+3*256)/4

下述为go1.23源码逻辑src/runtime/slice.go :

// growslice 为一个切片分配新的底层存储。
//
// 参数:
// oldPtr = 指向切片底层数组的指针
// newLen = 新的长度(= oldLen + num)
// oldCap = 原始切片的容量
// num = 正在添加的元素数量
// et = 元素类型
// 返回值:
// newPtr = 指向新底层存储的指针
// newLen = 新的长度与传参相同
// newCap = 新底层存储的容量
//
// 要求 uint(newLen) > uint(oldCap)。
// 假设原始切片的长度为 newLen - num
//
// 分配一个至少能容纳 newLen 个元素的新底层存储。
// 已存在的条目 [0, oldLen) 被复制到新的底层存储中。
// 添加的条目 [oldLen, newLen) 不会被 growslice 初始化
// (虽然对于包含指针的元素类型,它们会被清零)。调用者必须初始化这些条目。
// 尾随条目 [newLen, newCap) 被清零。
//
// growslice 的特殊调用约定使得调用此函数的生成代码更简单。特别是,它接受并返回
// 新的长度,这样旧的长度不需要被保留/恢复,而新的长度返回时也不需要被保留/恢复。
func growslice(oldPtr unsafe.Pointer, newLen, oldCap, num int, et *_type) slice {oldLen := newLen - num// ... 函数非核心部分省略if newLen < 0 {panic(errorString("growslice: len out of range"))}if et.Size_ == 0 {// append不应该创建一个指针为nil但长度非零的切片。// 我们假设在这种情况下,append不需要保留oldPtr。return slice{unsafe.Pointer(&zerobase), newLen, newLen}}// 1.计算新容量newcap := nextslicecap(newLen, oldCap)var overflow boolvar lenmem, newlenmem, capmem uintptr// 针对常见的 et.Size 进行优化// 对于1我们不需要任何除法/乘法。// 对于 goarch.PtrSize, 编译器会优化除法/乘法为一个常量移位。// 对于2的幂,使用变量移位。noscan := !et.Pointers()// 2.内存对齐switch {case et.Size_ == 1:lenmem = uintptr(oldLen)newlenmem = uintptr(newLen)capmem = roundupsize(uintptr(newcap), noscan)overflow = uintptr(newcap) > maxAllocnewcap = int(capmem)case et.Size_ == goarch.PtrSize:lenmem = uintptr(oldLen) * goarch.PtrSizenewlenmem = uintptr(newLen) * goarch.PtrSizecapmem = roundupsize(uintptr(newcap)*goarch.PtrSize, noscan)overflow = uintptr(newcap) > maxAlloc/goarch.PtrSizenewcap = int(capmem / goarch.PtrSize)case isPowerOfTwo(et.Size_):var shift uintptrif goarch.PtrSize == 8 {shift = uintptr(sys.TrailingZeros64(uint64(et.Size_))) & 63} else {shift = uintptr(sys.TrailingZeros32(uint32(et.Size_))) & 31}lenmem = uintptr(oldLen) << shiftnewlenmem = uintptr(newLen) << shiftcapmem = roundupsize(uintptr(newcap)<<shift, noscan)overflow = uintptr(newcap) > (maxAlloc >> shift)newcap = int(capmem >> shift)capmem = uintptr(newcap) << shiftdefault:lenmem = uintptr(oldLen) * et.Size_newlenmem = uintptr(newLen) * et.Size_capmem, overflow = math.MulUintptr(et.Size_, uintptr(newcap))capmem = roundupsize(capmem, noscan)newcap = int(capmem / et.Size_)capmem = uintptr(newcap) * et.Size_}// ... 函数非核心部分省略
}核心代码:
// nextslicecap 计算下一个合适的切片容量。
// 该函数用于在切片需要扩容时,确定新的容量大小。
//  newLen: 切片的新长度(所需容量)。
//  oldCap: 切片的旧容量。
// 返回值: 新的切片容量。
func nextslicecap(newLen, oldCap int) int {newcap := oldCap // 将新的容量初始化为旧的容量doublecap := newcap + newcap // 计算旧容量的两倍// 如果新长度大于旧容量的两倍,则直接使用新长度作为新容量// 这是为了避免频繁的扩容操作,当所需长度远大于当前容量时,直接分配所需的空间if newLen > doublecap {return newLen}// 设置一个阈值,用于区分小切片和大切片const threshold = 256// 对于容量小于阈值的小切片,新容量直接设置为旧容量的两倍// 这是因为小切片的扩容成本相对较低if oldCap < threshold {return doublecap}// 对于容量大于等于阈值的大切片,采用更保守的扩容策略for {//  从2倍增长(小切片)过渡到1.25倍增长(大切片)。//  该公式在两者之间提供平滑的过渡。//  (newcap + 3*threshold) >> 2 等价于 (newcap + 3*threshold) / 4//  这使得新容量的增长比例在1.25到2之间,并随着切片容量的增大而逐渐接近1.25newcap += (newcap + 3*threshold) >> 2// 需要检查 `newcap >= newLen` 以及 `newcap` 是否溢出。// newLen 保证大于零,因此当 newcap 溢出时,`uint(newcap) > uint(newLen)` 不成立。// 这允许使用相同的比较来检查两者。// 使用uint类型进行比较是为了处理溢出情况。如果newcap溢出变成负数,转换为uint类型后会变成一个很大的正数,从而使得比较仍然有效。if uint(newcap) >= uint(newLen) {break // 如果新容量足够大,则退出循环}}//  当 newcap 计算溢出时,将 newcap 设置为请求的容量。//  如果 newcap 小于等于 0,说明发生了溢出if newcap <= 0 {return newLen}return newcap // 返回计算出的新容量
}// roundupsize 返回 mallocgc 为指定大小分配的内存块的大小,减去任何用于元数据的内联空间。
//  size: 请求分配的内存大小。
//  noscan:  如果为 true,则表示该内存块不需要垃圾回收扫描。
// 返回值: mallocgc 实际分配的内存块大小。
func roundupsize(size uintptr, noscan bool) (reqSize uintptr) {reqSize = size // 初始化请求大小// 处理小对象(小于等于 maxSmallSize-mallocHeaderSize)if reqSize <= maxSmallSize-mallocHeaderSize {// 小对象。// 如果需要垃圾回收扫描 (noscan 为 false) 并且大小大于 minSizeForMallocHeader,则添加 mallocHeaderSize 用于存储元数据。// heapBitsInSpan(reqSize) 用于检查对象是否足够小到可以存储在堆的位图中,如果可以,则不需要 mallocHeader。if !noscan && reqSize > minSizeForMallocHeader { // !noscan && !heapBitsInSpan(reqSize)reqSize += mallocHeaderSize}// (reqSize - size) 为 mallocHeaderSize 或 0。如果添加了 mallocHeaderSize,我们需要从结果中减去它,因为 mallocgc 会再次添加它。// 这里是为了确保返回的大小是 mallocgc 实际分配的大小,而不是包含了头部之后的大小。// 进一步区分更小的对象和中等大小的对象,使用不同的查找表进行向上取整if reqSize <= smallSizeMax-8 {// 对于非常小的对象,使用 size_to_class8 和 class_to_size 查找表进行向上取整,以 8 字节为粒度。// divRoundUp(reqSize, smallSizeDiv) 计算 reqSize 在 smallSizeDiv 粒度下的向上取整值。// class_to_size[...] 获取对应大小类的实际分配大小。// 最后减去 (reqSize - size) 移除之前可能添加的 mallocHeaderSize。return uintptr(class_to_size[size_to_class8[divRoundUp(reqSize, smallSizeDiv)]]) - (reqSize - size)}// 对于中等大小的对象,使用 size_to_class128 和 class_to_size 查找表进行向上取整,以 128 字节为粒度。return uintptr(class_to_size[size_to_class128[divRoundUp(reqSize-smallSizeMax, largeSizeDiv)]]) - (reqSize - size)}// 处理大对象(大于 maxSmallSize-mallocHeaderSize)// 大对象。将 reqSize 向上对齐到下一页。检查溢出。reqSize += pageSize - 1 // 将 reqSize 增加到下一页边界之前// 检查溢出。如果 reqSize 加上 pageSize - 1 后反而变小了,说明发生了溢出。if reqSize < size {return size // 返回原始大小,避免分配过大的内存}// 通过按位与运算将 reqSize 对齐到下一页边界。return reqSize &^ (pageSize - 1)
}

三、问题

【引申1】 [3]int 和 [4]int 是同一个类型吗?

不是。因为数组的长度是类型的一部分,这是与 slice 不同的一点。

【引申2】 下面的代码输出是什么?

说明:例子来自雨痕大佬《Go学习笔记》第四版,P43页。这里我会进行扩展,并会作图详细分析。

package mainimport "fmt"func main() {slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}s1 := slice[2:5]s2 := s1[2:6:7]s2 = append(s2, 100)s2 = append(s2, 200)s1[2] = 20fmt.Println(s1)fmt.Println(s2)fmt.Println(slice)
}

结果:

[2 3 20]
[4 5 6 7 100 200]
[0 1 2 3 20 5 6 7 100 9]

s1slice 索引2(闭区间)到索引5(开区间,元素真正取到索引4),长度为3,容量默认到数组结尾,为8。 s2s1 的索引2(闭区间)到索引6(开区间,元素真正取到索引5),容量到索引7(开区间,真正到索引6),为5。

slice origin

接着,向 s2 尾部追加一个元素 100:

s2 = append(s2, 100) 

s2 容量刚好够,直接追加。不过,这会修改原始数组对应位置的元素。这一改动,数组和 s1 都可以看得到。

append 100

再次向 s2 追加元素200:

s2 = append(s2, 200) 

这时,s2 的容量不够用,该扩容了。于是,s2 另起炉灶,将原来的元素复制新的位置,扩大自己的容量。并且为了应对未来可能的 append 带来的再一次扩容,s2 会在此次扩容的时候多留一些 buffer,将新的容量将扩大为原始容量的2倍,也就是10了。

append 200

最后,修改 s1 索引为2位置的元素:

s1[2] = 20

这次只会影响原始数组相应位置的元素。它影响不到 s2 了,人家已经远走高飞了。

s1[2]=20

再提一点,打印 s1 的时候,只会打印出 s1 长度以内的元素。所以,只会打印出3个元素,虽然它的底层数组不止3个元素。

参考链接

1.Go 程序员面试笔试宝典

2.《Go学习笔记》

3.golangSlice的扩容规则

相关文章:

02.Golang 切片(slice)源码分析(一、定义与基础操作实现)

Golang 切片&#xff08;slice&#xff09;源码分析&#xff08;一、定义与基础操作实现&#xff09; 注意当前go版本代码为1.23 一、定义 slice 的底层数据是数组&#xff0c;slice 是对数组的封装&#xff0c;它描述一个数组的片段。两者都可以通过下标来访问单个元素。 数…...

当生产了~/qt-arm/bin/qmake,可以单独编译其他-源码的某个模块,如下,编译/qtmultimedia

cd ~/qt-everywhere-src-5.15.2/qtmultimedia # 设置交叉编译器和 qmake 路径 export CC/usr/bin/aarch64-linux-gnu-gcc export CXX/usr/bin/aarch64-linux-gnu-g export QMAKE~/qt-arm/bin/qmake # 使用已安装的 qmake export QT_INSTALL_PREFIX~/qt-arm # 安装路径 # 配…...

WordPress 网站上的 jpg、png 和 WebP 图片插件

核心功能 1. 转换 AVIF 并压缩 AVIF 将您 WordPress 网站上的 jpg、png 和 WebP 图片转换为 AVIF 格式&#xff0c;并根据您设置的压缩级别压缩 AVIF 图片。如果原始图片已经是 WordPress 6.5 以上支持的 AVIF 格式&#xff0c;则原始 AVIF 图片将仅被压缩。 2. 转换 WebP 并…...

构造+简单树状

昨日的牛客周赛算是比较简单的&#xff0c;其中最后一道构造题目属实眼前一亮。 倒数第二个题目也是一个很好的模拟题目&#xff08;考验对二叉树的理解和代码的细节&#xff09; 给定每一层的节点个数&#xff0c;自己拟定一个父亲节点&#xff0c;构造一个满足条件的二叉树。…...

Flask支持哪些日志框架

目录 ✅ Flask 默认支持的日志框架 ✅ 默认推荐:logging(标准库) ✅ 进阶推荐:Loguru(更优雅的日志库) ✅ Flask 日志级别说明(与标准库一致) ✅ 生产环境建议 ✅ 总结推荐 在 Flask 中,默认的日志系统是基于 Python 标准库 logging 模块 构建的。 ✅ Flask 默认…...

健康养生指南:解锁活力生活的科学密码

健康是人生最珍贵的财富&#xff0c;在快节奏的现代生活中&#xff0c;掌握科学的养生方法至关重要。虽然不借助中医理念&#xff0c;我们依然可以从饮食、运动、睡眠等多个方面入手&#xff0c;打造健康生活方式。 合理的饮食是健康的基石。遵循均衡饮食原则&#xff0c;保证每…...

SAR图像压缩感知

SAR图像压缩感知 matlab代码 对应着汕大闫老师的那本压缩感知及其应用&#xff0c;有需要的可以看一下&#xff01;&#xff01; SAR图像压缩感知/baboon.bmp , 66616 SAR图像压缩感知/camera.bmp , 66616 SAR图像压缩感知/DWT.m , 1265 SAR图像压缩感知/Gauss.m , 373 SAR图像…...

定时器设计

定时器设计的必要性 服务器中的定时器设计具有多方面的必要性&#xff0c;主要体现在以下几个关键方面&#xff1a; 任务调度与管理 定时任务执行&#xff1a;服务器常常需要执行一些定时性的任务&#xff0c;如定时备份数据、定时清理缓存、定时更新系统日志等。通过定时器可…...

Spring Boot整合Kafka实战指南:从环境搭建到消息处理全解析

一、环境准备 安装 Kafka 下载 Kafka&#xff1a;从 Apache Kafka 官网下载对应版本的 Kafka。 解压并启动 Kafka&#xff1a; # 启动 Zookeeper&#xff08;Kafka 依赖 Zookeeper&#xff09; bin/zookeeper-server-start.sh config/zookeeper.properties# 启动 Kafka bin/ka…...

(done) 补充:xv6 的一个用户程序 init 是怎么启动的 ?它如何启动第一个 bash ?

先看 main.c 从函数名来看&#xff0c;比较相关的就 userinit() 和 scheduler() #include "types.h" #include "param.h" #include "memlayout.h" #include "riscv.h" #include "defs.h"volatile static int started 0;//…...

AI 搜索引擎 MindSearch

背景 RAG是一种利用文档减少大模型的幻觉&#xff0c;AI搜索也是 AI 搜索引擎 MindSearch 是一个开源的 AI 搜索引擎框架&#xff0c;具有与 Perplexity.ai Pro 相同的性能。您可以轻松部署它来构建您自己的搜索引擎&#xff0c;可以使用闭源 LLM&#xff08;如 GPT、Claude…...

HTML简单语法标签(后续实操:云备份项目)

以下是一些 HTML 的简单语法标签及其功能介绍&#xff1a; 基本结构标签 <!DOCTYPE html>&#xff1a;声明文档类型为 HTML5<html>&#xff1a;HTML 文档的根标签<head>&#xff1a;包含文档元数据&#xff08;如标题、字符编码等&#xff09;<title>…...

CentOS 和 RHEL

CentOS 和 RHEL&#xff08;Red Hat Enterprise Linux&#xff09;关系非常紧密&#xff0c;简而言之&#xff1a; CentOS 最初是 RHEL 的免费、开源克隆版&#xff0c;几乎与 RHEL 二进制兼容。 CentOS 原是 RHEL 的“免费双胞胎”&#xff0c;但已被放弃&#xff0c;现在推荐…...

java----------->代理模式

目录 什么是代理模式&#xff1f; 为什么会有代理模式&#xff1f; 怎么写代理模式&#xff1f; 实现代理模式总共需要三步&#xff1a; 什么是代理模式&#xff1f; 代理模式&#xff1a;给目标对象提供一个代理对象&#xff0c;并且由代理对象控制目标对象的引用 代理就是…...

Wpf学习片段

IRegionManager 和IContainerExtension IRegionManager 是 Prism 框架中用于管理 UI 区域&#xff08;Regions&#xff09;的核心接口&#xff0c;它实现了模块化应用中视图&#xff08;Views&#xff09;的动态加载、导航和生命周期管理。 IContainerExtension 是依赖注入&…...

智能手表测试用例文档

智能手表测试用例文档 产品名称&#xff1a;智能手表 A1 版本号&#xff1a;FW v1.0.0 测试负责人&#xff1a;[填写] 编写时间&#xff1a;2025-xx-xx 文档状态&#xff1a;初次版本 &#x1f4c1; 测试用例结构说明 字段描述用例编号测试用例唯一编号&#xff0c;如 TC-FUN…...

密码学--希尔密码

一、实验目的 1、通过实现简单的古典密码算法&#xff0c;理解密码学的相关概念 2、理解明文、密文、加密密钥、解密密钥、加密算法、解密算法、流密码与分组密码等。 二、实验内容 1、题目内容描述 ①定义分组字符长度 ②随机生成加密密钥&#xff0c;并验证密钥的可行性 …...

配置Hadoop集群-集群配置

以下是 Hadoop 集群的核心配置步骤&#xff0c;基于之前的免密登录和文件同步基础&#xff0c;完成 Hadoop 分布式环境的搭建&#xff1a; 1. 集群规划 假设集群包含 3 个节点&#xff1a; master&#xff1a;NameNode、ResourceManagerslave1&#xff1a;DataNode、NodeMana…...

第三方软件测评中心分享:软件功能测试类型和测试工具

在数字化时代&#xff0c;软件测试已成为确保产品质量的重要环节。功能测试作为软件测试中的核心部分&#xff0c;关注于软件产品是否按预期功能正常运作。 软件功能测试可以按不同的方式进行分类&#xff0c;主要包括以下几种类型&#xff1a;   1.正功能测试&#xff1a;验…...

Profibus DP主站与Modbus RTU/TCP网关与海仕达变频器轻松实现数据交互

Profibus DP主站与Modbus RTU/TCP网关与海仕达变频器轻松实现数据交互 Profibus DP主站转Modbus RTU/TCP&#xff08;XD-MDPBm20&#xff09;网关在Profibus总线侧实现主站功能&#xff0c;在Modbus串口侧实现从站功能。可将ProfibusDP协议的设备&#xff08;如&#xff1a;海…...

多视角系统,视角之间的切换,输入操作。无人机Pawn视角的实现

一.创建自己的PlayerController。它相当于是灵魂&#xff0c;穿梭在不同Pawn之间。也即是切换视角。不同输入的响应也写在这里。这样即使&#xff0c;都有鼠标操作&#xff0c;也能区分。避免了代码的重复耦合。也可以叫做视角系统。 class LZJGAMEMODE_API ALZJPlayerControl…...

[学习]RTKLib详解:ionex.c、options.c与preceph.c

RTKLib详解&#xff1a;ionex.c、options.c与preceph.c 本文是 RTKLlib详解 系列文章的一篇&#xff0c;目前该系列文章还在持续总结写作中&#xff0c;以发表的如下&#xff0c;有兴趣的可以翻阅。 [学习] RTKlib详解&#xff1a;功能、工具与源码结构解析 [学习]RTKLib详解&…...

【Linux笔记】——进程信号的保存

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;Linux &#x1f339;往期回顾&#x1f339;&#xff1a;【Linux笔记】——进程信号的产生 &#x1f516;流水不争&#xff0c;争的是滔滔不 一、信号的相关概念二、信…...

教育机构教务管理系统哪个好?

在当今教育培训行业快速发展的背景下&#xff0c;一个高效、专业的教务管理系统已成为教育机构提升运营效率、优化教学质量的关键工具。本文将深入分析爱耕云教务管理系统的核心优势&#xff0c;通过具体功能解析和代码示例展示其技术实现方式&#xff0c;并对比市场上其他主流…...

ZYNQ笔记(二十):Clocking Wizard 动态配置

版本&#xff1a;Vivado2020.2&#xff08;Vitis&#xff09; 任务&#xff1a;ZYNQ PS端 通过 AXI4Lite 接口配置 Clocking Wizard IP核输出时钟频率 目录 一、介绍 二、寄存器定义 三、配置 四、PS端代码 一、介绍 Xilinx 的 Clock Wizard IP核 用于在 FPGA 中生成和管理…...

电商平台一站式网络安全架构设计指南

摘要&#xff1a;据 Gartner 统计&#xff0c;采用一体化安全方案的电商企业数据泄露成本降低 67%。本文从攻击链分析到防御体系构建&#xff0c;详解如何实现网络层、应用层、数据层的协同防护。 一、电商安全威胁全景图&#xff08;2024 攻击态势&#xff09; 1.1 攻击者完…...

烟花爆竹储存需要注意哪些问题

烟花爆竹储存需要注意哪些问题 烟花爆竹作为易燃易爆物品&#xff0c;其储存安全至关重要。不当的储存方式不仅可能导致产品失效&#xff0c;更可能引发火灾、爆炸等严重事故。以下是烟花爆竹储存需要注意的几个关键问题&#xff1a; 一、储存场所选择 必须选择专用仓库储存…...

C++11详解

文章目录 前言一、列表初始化1.1 {} 初始化1.2 initializer_list 类型 三、声明3.1 auto3.2 decltype 四、右值引用和移动语义4.1 左值引用和右值引用4.2 移动语义 五、可变参数模板六、lambda表达式各部分详细解释示例代码代码解释 七、包装器八、bind注意事项 前言 C11在系统…...

VLM-RL:用于安全自动驾驶的统一视觉语言模型和强化学习框架——论文阅读

《VLM-RL: A Unified Vision Language Models and Reinforcement Learning Framework for Safe Autonomous Driving》2024年12月发表&#xff0c;来自Wisconsin Madison分校和Purdue大学的论文。 近年来&#xff0c;基于强化学习&#xff08;RL&#xff09;的学习驾驶策略的方法…...

新手安装java所有工具(jdk、idea,Maven,数据库)

新手安装JAVA工具 介绍JDK11IDEA 2025.1Maven数据库&#xff08;Navicat Premium Lite&#xff09; 介绍 涉及安装JAVA所需的各种工具 JDK&#xff08;以JDK11为例&#xff09;IDEA&#xff08;以2025.1为例&#xff09;Maven&#xff08;以3.8.8为例&#xff09;数据库&…...

hive在配置文件中添加了hive.metastore.uris之后进入hive输入命令报错

在hive-site.xml文件中加入配置hive.metastore.uris启动hive后报错 <property><name>hive.metastore.uris</name><value>thrift://node154:9083</value></property> 加完属性就需要手动启动metastore服务&#xff0c;因为不使用 Zookeepe…...

Hive原理

Hive 是构建在 Hadoop 上的数据仓库工具,其核心原理是通过类 SQL 语言(HiveQL)将结构化数据查询转换为分布式计算任务(如 MapReduce、Tez、Spark),并利用 HDFS 存储数据。以下是 Hive 的核心原理和架构: 1. 核心设计思想‌ ‌数据仓库抽象‌:将 HDFS 上的文件抽象为‌…...

cursor 出现 unauthorized request

文档出自&#xff1a;https://www.kdocs.cn/l/csE3iuSauHoS...

uniapp|商品列表加入购物车实现抛物线动画效果、上下左右抛入、多端兼容(H5、APP、微信小程序)

以uniapp框架为基础,详细解析商品列表加入购物车抛物线动画的实现方案。通过动态获取商品点击位置与购物车坐标,结合CSS过渡动画模拟抛物线轨迹,实现从商品图到购物车图标的动态效果。 目录 核心实现原理坐标动态计算抛物线轨迹模拟​动画元素控制代码实现详解模板层设计脚本…...

点下4个Winform UI开源控件库

从零学习构建一个完整的系统 今天一起来盘点下4个Winform UI开源控件库&#xff0c;有.Net Framework&#xff0c;也有.Net Core。 1、支持.Net 7的开源UI组件框架 项目简介 这是一个基于.Net Framework、.Net 6开发的&#xff0c;WinForm开源UI框架&#xff0c;框架包含常…...

【AI】mcp server本质就是一个接口服务么

以下为元宝的回答&#xff1a; 你的理解非常准确&#xff01;​​MCP Server​​本质上是一个接口服务&#xff0c;但其设计目标、交互逻辑和使用场景与传统后端接口存在显著差异。以下是两者的对比分析&#xff1a; ​​1. 核心定位差异​​ ​​维度​​​​MCP Server​​…...

chalrs正常使用一段时间后开启代理访问网页 显示“不是私密链接”解决办法

chalrs正常使用一段时间后开启代理访问网页 显示“不是私密链接”解决办法 背景&#xff1a; charles用了好长时间了&#xff0c;最近发现打开charles有些软件无法上网&#xff0c;浏览器访问网页提示“您的连接不是私密链接”&#xff0c;按照网上的教程重装了几次证书&#x…...

如何通过DNS解析实现负载均衡?

在当今的互联网时代&#xff0c;随着网络应用的飞速发展&#xff0c;网站和各类在线服务面临着海量的用户请求。为了保障服务的高可用性和高性能&#xff0c;负载均衡技术应运而生。DNS&#xff08;域名系统&#xff09;负载均衡作为其中一种重要的实现方式&#xff0c;凭借其简…...

uni-app微信小程序登录流程详解

文章目录 uni-app微信小程序登录流程实战详解微信小程序登录流程概述1. 获取登录凭证&#xff08;code&#xff09;2. 发送登录请求3. 保存登录态4. 登录状态管理5. 应用登录状态请求拦截器中添加 token自动登录页面路由守卫 使用 Vuex 集中管理登录状态登录组件示例登录流程最…...

基于LVS和Keepalived实现高可用负载均衡架构

目录 一、资源清单 二、修改主机名 三、配置调度器 四、配置Web节点服务器&#xff08;web1、web2&#xff09; 五、测试负载均衡 六、测试LVSKeepalived高可用群集 一、资源清单 主机 操作系统 IP地址 lb01 OpenEuler24.03 192.168.16.142 lb02 OpenEuler24.03 …...

微信小程序仿淘宝拍照/照片点位识图、点位裁剪生图、图片裁剪组件、图片点位框选、裁剪生成图片,canvasToImg

实现效果 效果&#xff1a; 1.微信小程序仿淘宝拍照/照片点位识图、根据点位裁剪生图、图片可裁剪、图片高度可控 2.识别点位自动生成标准构图方案&#xff0c;支持手动微调实现像素级精准裁剪 3.可以根据接口识别的点位信息实现拍照/相册图片特征点自动识别并裁剪 实现步骤 …...

EnumUtils:你的枚举“变形金刚“——让枚举操作不再手工作业

各位枚举操控师们好&#xff01;今天要介绍的是Apache Commons Lang3中的EnumUtils工具类。这个工具就像枚举界的"瑞士军刀"&#xff0c;能让你的枚举操作从石器时代直接跃迁到星际文明&#xff01; 一、为什么需要EnumUtils&#xff1f; 手动操作枚举就像&#xf…...

在Taro中开发一个跨端Svg组件,同时支持小程序、H5、React Native

Taro系列中一直没有跨端的绘图工具&#xff0c;小程序端支持canvas但是不支持svg&#xff0c;RN端有 react-native-svg 支持svg&#xff0c;但是没有很好原生的canvas插件&#xff0c;社区的canvas都是基于WebView实现的&#xff0c;或者skia&#xff0c;这个插件的书写方式和c…...

大型视频学习平台项目问题解决笔记

一 数据库大量读操作导致数据库压力过大的解决方案 1. 优化SQL语句 2. 缓存 二 数据库大量写操作导致数据库压力过大的解决方案 1. 优化SQL语句 2. 改同步写为异步写——解决复杂事务的高并发写 3. 合并写请求——解决简单事务的高并发写&#xff08;额外实现一个异步操作来…...

day18-数据结构引言

一、 概述 数据结构&#xff1a;相互之间存在一种或多种特定关系的数据元素的集合。 1.1 特定关系&#xff1a; 1. 逻辑结构 2.物理结构&#xff08;在内存当中的存储关系&#xff09; 逻辑结构物理结构集合&#xff0c;所有数据在同一个集合中&#xff0c;关系平等顺…...

Android音频解码中的时钟同步问题:原理、挑战与解决方案

一、为什么音频同步如此重要&#xff1f; 在多媒体播放系统中&#xff0c;音频同步问题直接影响用户体验。根据行业研究数据&#xff1a; • 15ms以上的同步偏差&#xff1a;53%的用户能感知到音画不同步 • 超过100ms的偏差&#xff1a;会导致明显的"口型对不上"现…...

深入浅出 iOS 对象模型:isa 指针 与 Swift Metadata

在 iOS 开发中&#xff0c;我们经常听到两个看似神秘的词&#xff1a;isa 指针 和 Metadata。这两个概念分别源自 Objective-C 和 Swift 的对象系统&#xff0c;是我们理解底层运行机制、优化性能乃至调试疑难问题的关键。今天我们就来聊一聊&#xff0c;它们到底是什么&#x…...

ARMV8 RK3399 u-boot TPL启动流程分析 --crt0.S

上一篇介绍到start.S 最后一个指令是跳转到_main, 接下来分析 __main 都做了什么 arch/arm/lib/crt0.S __main 注释写的很详细&#xff0c;主要分为5步 1. 准备board_init_f的运行环境 2. 跳转到board_init_f 3. 设置broad_init_f 申请的stack 和 GD 4. 完整u-boot 执行re…...

Lynx-字节跳动跨平台框架多端兼容Android, iOS, Web 原生渲染

介绍 字节跳动近期开源的跨平台框架Lynx被视为一项重要的技术创新。相较于市场上已有的解决方案如React Native (RN) 和Flutter&#xff0c;Lynx具有独特的特性。 首先&#xff0c;Lynx采用轻量级JavaScript逻辑设计&#xff0c;DOM节点构建完全置于Native层&#xff0c;确保U…...

手机换地方ip地址会变化吗?深入解析

在移动互联网时代&#xff0c;我们经常带着手机穿梭于不同地点&#xff0c;无论是出差旅行还是日常通勤。许多用户都好奇&#xff1a;当手机更换使用地点时&#xff0c;IP地址会随之改变吗&#xff1f;本文将深入解析手机IP地址的变化机制&#xff0c;帮助您全面了解这一常见但…...