Java转Go日记(一):Slice解密
1.切片通过函数,传的是什么?
package mainimport ("fmt""reflect""unsafe"
)func main() {s := make([]int, 5, 10)PrintSliceStruct(&s)test(s)
}func test(s []int) {PrintSliceStruct(&s)
}func PrintSliceStruct(s *[]int) {ss := (*reflect.SliceHeader)(unsafe.Pointer(s))fmt.Println("slice struct: %+v, slice is %v\n", ss, s)
}
切片是引用类型:
-
切片在函数间传递时,
SliceHeader(slice 的内部结构) 会被复制,但Data指针指向的底层数组是共享的。因此,修改切片元素会影响所有引用该底层数组的切片。
2.在函数里面改变切片,函数外的切片会被影响吗?
package mainimport ("fmt""reflect""unsafe"
)func main() {s := make([]int, 5, 10)case1(s)case2(s)PrintSliceStruct(&s)
}func PrintSliceStruct(s *[]int) {ss := (*reflect.SliceHeader)(unsafe.Pointer(s))fmt.Println("slice struct: %+v, slice is %v\n", ss, s)
}// 底层数组变化
func case2(s []int) {s = append(s, 0)s[1] = 1PrintSliceStruct(&s)
}// 底层数组不变
func case1(s []int) {s[1] = 1PrintSliceStruct(&s)
}
总结:
| 操作 | 是否影响外部切片 | 说明 |
| s[i] = x | ✅ 是 | 直接修改底层数组 |
| append(未扩容) | ⚠️ 部分影响(len 不变) | 修改元素会影响,但 len 不会变 |
| append(扩容) | ❌ 否 | 新切片指向新数组 |
| 传递 *[]int | ✅ 是 | 直接修改外部切片 |
3.截取切片
通过操作得到的新slice和原slice是什么关系?
(1) 底层数组共享
-
新切片和原切片指向同一个底层数组,修改其中一个的元素会影响另一个。
(2) 新切片的长度和容量变化
-
新切片的
len取决于截取的范围(s[low:high]→len = high - low)。 -
新切片的
cap是原切片cap - low(即从low开始到原底层数组末尾)。
(3) append 是否触发扩容
-
如果新切片
append后未超过底层数组容量,修改会影响原切片。 -
如果
append后超过容量,Go 会分配新数组,此时新切片与原切片不再共享底层数组。
package mainimport ("fmt""reflect""unsafe"
)func main() {s := make([]int, 5, 10)case1(s)case2(s)case3(s)case4(s)PrintSliceStruct(&s)
}func PrintSliceStruct(s *[]int) {ss := (*reflect.SliceHeader)(unsafe.Pointer(s))fmt.Println("slice struct: %+v, slice is %v\n", ss, s)
}// 截取获得新切片
func case4(s []int) {s1 := s[2:]PrintSliceStruct(&s1)
}// 截取[len(s) - 1, ]区间元素
func case3(s []int) {s = s[len(s)-1:]PrintSliceStruct(&s)
}// 截取[1,2]区间元素
func case2(s []int) {s = s[1:3]PrintSliceStruct(&s)
}// 截取0号以后的元素
func case1(s []int) {s = s[1:]PrintSliceStruct(&s)
}
output:
slice struct: %+v, slice is %v&{1374390288392 4 9} &[0 0 0 0]
slice struct: %+v, slice is %v&{1374390288392 2 9} &[0 0]
slice struct: %+v, slice is %v&{1374390288416 1 6} &[0]
slice struct: %+v, slice is %v&{1374390288400 3 8} &[0 0 0]
slice struct: %+v, slice is %v&{1374390288384 5 10} &[0 0 0 0 0]
4.删除元素:
package mainimport ("fmt""reflect""unsafe"
)func main() {s := []int{0, 1, 2, 3, 4}_ = s[4]PrintSliceStruct(&s)s1 := append(s[:1], s[2:]...)PrintSliceStruct(&s1)PrintSliceStruct(&s)// 访问原切片_ = s[4]// 访问原切片中删除了一个元素的切片_ = s1[4]
}func PrintSliceStruct(s *[]int) {ss := (*reflect.SliceHeader)(unsafe.Pointer(s))fmt.Println("slice struct: %+v, slice is %v\n", ss, s)
}
output:
slice struct: %+v, slice is %v&{1374389641552 5 5} &[0 1 2 3 4]
slice struct: %+v, slice is %v&{1374389641552 4 5} &[0 2 3 4]
slice struct: %+v, slice is %v&{1374389641552 5 5} &[0 2 3 4 4]
panic: runtime error: index out of range [4] with length 4goroutine 1 [running]:
main.main()/Users/admin/GolandProjects/Go_study/slice/slice_4/main/slice_4.go:23 +0x1a8
-
关键发现:
s的内容也被修改了! -
因为
s和s1共享底层数组,append操作修改了数组内容
最后一个4是原数组的残留值
5.添加元素
package mainimport ("fmt""reflect""unsafe"
)func main() {case1()case2()case3()}func case3() {s1 := make([]int, 3, 3)s2 := append(s1, 1)PrintSliceStruct(&s1)PrintSliceStruct(&s2)
}func case2() {s1 := make([]int, 3, 4)s2 := append(s1, 1)PrintSliceStruct(&s1)PrintSliceStruct(&s2)
}func case1() {s1 := make([]int, 3, 3)s1 = append(s1, 1)PrintSliceStruct(&s1)
}func PrintSliceStruct(s *[]int) {ss := (*reflect.SliceHeader)(unsafe.Pointer(s))fmt.Println("slice struct: %+v, slice is %v\n", ss, s)
}
Output:
slice struct: %+v, slice is %v&{1374390272048 4 6} &[0 0 0 1]
slice struct: %+v, slice is %v&{1374390296608 3 4} &[0 0 0]
slice struct: %+v, slice is %v&{1374390296608 4 4} &[0 0 0 1]
slice struct: %+v, slice is %v&{1374390231160 3 3} &[0 0 0]
slice struct: %+v, slice is %v&{1374390272096 4 6} &[0 0 0 1]
6.slice深度拷贝的方法
相关文章:
Java转Go日记(一):Slice解密
1.切片通过函数,传的是什么? package mainimport ("fmt""reflect""unsafe" )func main() {s : make([]int, 5, 10)PrintSliceStruct(&s)test(s) }func test(s []int) {PrintSliceStruct(&s) }func PrintSliceStr…...
MySQL 锁机制全景图:分类、粒度与示例一图掌握
✅ 一、按粒度分类(锁的范围大小) 1. 表级锁(Table Lock) 锁住整张表粒度大,开销小,并发性差常见于:MyISAM 引擎 📌 示例: LOCK TABLES user WRITE; -- 会锁住整个 u…...
STM32江科大----------PID算法
声明:本人跟随b站江科大学习,本文章是观看完视频后的一些个人总结和经验分享,也同时为了方便日后的复习,如果有错误请各位大佬指出,如果对你有帮助可以点个赞小小鼓励一下,本文章建议配合原视频使用❤️ 如…...
架构师面试(二十九):TCP Socket 编程
问题 今天考察网络编程的基础知识。 在基于 TCP 协议的网络 【socket 编程】中可能会遇到很多异常,在下面的相关描述中说法正确的有哪几项呢? A. 在建立连接被拒绝时,有可能是因为网络不通或地址错误或 server 端对应端口未被监听&#x…...
基础学习(4): Batch Norm / Layer Norm / Instance Norm / Group Norm
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言1 batch normalization(BN)2 Layer normalization (LN)3 instance normalization (IN)4 group normalization (GN)总结 前言 对 norm/batch/instance/group 这…...
局域网内Docker镜像共享方法
在局域网内将Docker镜像构建并传输到另一台电脑,可以通过以下几种方法实现。以下是具体步骤及注意事项,结合不同场景的适用方案: 方法一:使用 docker save 和 docker load 传输镜像文件 步骤说明 在构建机上保存镜像 通过 docker…...
Idea集成AI:CodeGeeX开发
当入职新公司,或者调到新项目组进行开发时,需要快速熟悉项目代码 而新的项目代码,可能有很多模块,很多的接口,很复杂的业务逻辑,更加有与之前自己的代码风格不一致的现有复杂代码 更别提很多人写代码不喜…...
HTTP HTTPS RSA
推荐阅读 小林coding HTTP篇 文章目录 HTTP 80HTTP 响应码1xx:信息性状态码(Informational)2xx:成功状态码(Success)3xx:重定向状态码(Redirection)4xx:客户端…...
【深度学习与大模型基础】第10章-期望、方差和协方差
一、期望 ——————————————————————————————————————————— 1. 期望是什么? 期望(Expectation)可以理解为“长期的平均值”。比如: 掷骰子:一个6面骰子的点数是1~6&#x…...
Elasticvue-轻量级Elasticsearch可视化管理工具
Elasticvue一个免费且开源的 Elasticsearch 在线可视化客户端,用于管理 Elasticsearch 集群中的数据,完全支持 Elasticsearch 版本 8.x 和 7.x. 功能特色: 集群概览索引和别名管理分片管理搜索和编辑文档REST 查询快照和存储库管理支持国际…...
危化品经营单位安全生产管理人员备考要点
危化品经营单位安全生产管理人员备考要点 📌 考试核心内容 ✅ 必考法规: 《危险化学品安全管理条例》重点条款(如经营许可条件) GB 18218-2018《重大危险源辨识》新标准 安全生产法律责任(罚款金额/刑事责任&…...
【python】OpenCV—Tracking(10.6)—People Counting
文章目录 1、功能描述2、代码实现3、效果展示4、完整代码5、涉及到的库函数6、参考来自 更多有趣的代码示例,可参考【Programming】 1、功能描述 借助 opencv-python,用 SSD 人形检测模型和质心跟踪方法实现对人群的计数 基于质心的跟踪可以参考 【pyt…...
使用KeilAssistant代替keil的UI界面
目录 一、keil Assistant的优势和缺点 二、使用方法 (1)配置keil的路径 (2)导入并使用工程 (3)默认使用keil自带的ARM编译器而非GUN工具链 一、keil Assistant的优势和缺点 在日常学…...
FreeRTOS菜鸟入门(五)·空闲任务与阻塞延时的实现
目录 1. 实现空闲任务 1.1 定义空闲任务的栈 1.2 定义空闲任务的任务控制块 1.3 创建空闲任务 2. 实现阻塞延时 2.1 vTaskDelay()函数 2.2 修改 vTaskSwitchContext()函数 3. SysTick 中断服务函数 4. SysTick 初始化函数 通过之前我们了解知道,任…...
Doris部署生产集群最低要求的部署方案
Doris生产集群最低部署方案(2025年4月版) 一、节点规划与数量 1. FE节点(Frontend) 数量:至少 3个节点(1个Follower 2个 Observer),确保高可用(HA)。角色分…...
JBOSS反序列化漏洞解析与防范策略CVE-2017-12149
JBOSS反序列化漏洞解析与防范策略 引言 JBOSS是一个流行的开源应用服务器,广泛应用于企业级应用程序的开发和部署。然而,由于其广泛的使用和复杂的架构,JBOSS也成为了黑客攻击的常见目标。近年来,多个JBOSS漏洞被曝光࿰…...
MySQL MVCC工作流程详解
MySQL MVCC工作流程详解 1. 基础概念 MVCC(多版本并发控制)是通过在每行记录后面保存多个版本来实现并发控制的技术,主要用于提供并发事务访问数据库时的读一致性。 2. 核心要素 2.1 事务ID(DB_TRX_ID) 每个事务都…...
Web3技术下数字资产数据保护的实践探索
在这个信息爆炸的时代,数字资产已经成为我们生活中不可或缺的一部分。随着Web3技术的兴起,它以其去中心化、透明性和安全性的特点,为数字资产的管理和保护提供了新的解决方案。本文将探讨Web3技术在数字资产数据保护方面的实践探索࿰…...
从PPT到PNG:Python实现的高效PPT转图工具
从PPT到PNG:Python实现的高效PPT转图工具 在日常工作中,PPT(PowerPoint)文件是我们常用的演示工具。然而,有时候我们需要将PPT的内容提取为图片格式(如PNG)以便于展示或保存。手动将每一页PPT保…...
使用 Java 8 Stream实现List重复数据判断
import java.util.*; import java.util.stream.Collectors;public class DeduplicateStreamExample {static class ArchiveItem {// 字段定义与Getter/Setter省略(需根据实际补充)private String mATNR;private String lIFNR;private String suppSpecMod…...
状态模式详解与真实场景案例(Java实现)
模式定义 状态模式(State Pattern) 允许对象在其内部状态改变时改变它的行为,使对象看起来像是修改了它的类。属于行为型设计模式,核心思想是将状态抽象为独立对象,不同状态下行为封装在不同状态类中。 解决的问题 …...
BitMap和RoaringBitmap:极致高效的大数据结构
目录 1、引言 2、BitMap:基础 2.1、核心原理 2.2、BitMap的优势 2.3、BitMap的局限性 3、RoaringBitmap:进化 3.1、分段策略 3.2、三种容器类型 3.2.1. ArrayContainer(数组容器) 3.2.2. BitMapContainer(位图容器) 3.2.3. RunContainer(行程容器) 3.3、行…...
【Java基础】Java集合遍历方式
前言 在Java编程中,集合(Collection)是存储和操作对象的核心工具。遍历集合是开发者最频繁的操作之一,但不同场景下选择合适的遍历方式至关重要。 一、基础遍历方式 1. 基本for循环 适用场景:仅适用于List等有序集…...
Rust-引用借用规则
目录 一、概述 二、借用规则 三、详细解释 3.1 第一条规则 3.2 第二条规则 3.3 第三条规则 四、总结 Welcome to Code Blocks blog 本篇文章主要介绍了 [Rust-引用借用规则] ❤博主广交技术好友,喜欢文章的可以关注一下❤ 一、概述 Rust为确保程序在运行时不…...
如何保障企业数据的安全?软件开发中的数据安全防护措施
引言 随着数字化转型的推进,数据已经成为企业最重要的资产之一。然而,随着数据量的增长,数据泄露、丢失和滥用的风险也不断增加。如何保障企业数据的安全,成为企业在进行软件开发时必须重点关注的问题。本文将介绍软件开发中的一些…...
Linux安装开源版MQTT Broker——EMQX服务器环境从零到一的详细搭建教程
零、EMQX各个版本的区别 EMQX各个版本的功能对比详情https://docs.emqx.com/zh/emqx/latest/getting-started/feature-comparison.html...
【软件工程大系】净室软件工程
净室软件工程(Cleanroom Software Engineering)是一种以缺陷预防(正确性验证)为核心的软件开发方法,旨在通过严格的工程规范和数学验证,在开发过程中避免缺陷的产生,而非依赖后期的测试和调试。…...
软考 系统架构设计师系列知识点之杂项集萃(49)
接前一篇文章:软考 系统架构设计师系列知识点之杂项集萃(48) 第76题 某文件管理系统在磁盘上建立了位视图(bitmap),记录磁盘的使用情况。若磁盘上物理块的编号依次为:0、1、2、……;…...
Day(21)--网络编程
网络编程 在网络通信协议下,不同计算机上运行的程序,进行的数据传输 应用场景:即使通信、网友对战、金融证券等等,不管是什么场景,都是计算机和计算机之间通过网络进行的数据传输 java.net 常见的软件架构 C/S&am…...
JVM 调优不再难:AI 工具自动生成内存优化方案
在 Java 应用程序的开发与运行过程中,Java 虚拟机(JVM)的性能调优一直是一项极具挑战性的任务,尤其是内存优化方面。不合适的 JVM 内存配置可能会导致应用程序出现性能瓶颈,甚至频繁抛出内存溢出异常,影响业…...
