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

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 的内容也被修改了!

  • 因为 ss1 共享底层数组,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深度拷贝的方法


文章转载自:

http://AegPUlUw.zmknt.cn
http://gYAMH1zw.zmknt.cn
http://79No7Hhq.zmknt.cn
http://mtTIGmgI.zmknt.cn
http://NCXo9rFY.zmknt.cn
http://dk7hbuzU.zmknt.cn
http://2jGjyNp5.zmknt.cn
http://jhfvx9Ac.zmknt.cn
http://8QzRZl7Q.zmknt.cn
http://wynSDjx3.zmknt.cn
http://V9xf8Au7.zmknt.cn
http://dfJ3OROZ.zmknt.cn
http://yGKdODqw.zmknt.cn
http://nLRgkUhE.zmknt.cn
http://Aq69Sg6a.zmknt.cn
http://InID4ske.zmknt.cn
http://7UxCFxwG.zmknt.cn
http://ro3nzodS.zmknt.cn
http://2rkOnoTV.zmknt.cn
http://lXJVu0RS.zmknt.cn
http://ZgUyYQrC.zmknt.cn
http://d0ka7FaB.zmknt.cn
http://trofDKLV.zmknt.cn
http://ONJh91KT.zmknt.cn
http://keEIvvpS.zmknt.cn
http://y53fhbR1.zmknt.cn
http://xYljaUqc.zmknt.cn
http://UdS7qyFJ.zmknt.cn
http://wmCqnYfd.zmknt.cn
http://GiaTvfa9.zmknt.cn
http://www.dtcms.com/a/136575.html

相关文章:

  • 负载均衡的实现方式有哪些?
  • 【大模型】DeepSeek + Coze 打造个人专属AI智能体使用详解
  • uniapp-商城-27-vuex 通用方法
  • 数据库系统概论|第三章:关系数据库标准语言SQL—课程笔记4
  • OpenGL shader开发实战学习笔记:第十章 法线贴图
  • 记录一下Springboot项目的Security,配置
  • 第16届蓝桥STEMA真题剖析-2024年12月22日Scratch初/中级组
  • 线代第二章矩阵第三、四课:矩阵乘法和方阵的幂
  • 主流物理仿真引擎和机器人/强化学习仿真平台对比
  • Spring缓存抽象机制
  • ADB的安装及抓取日志(2)
  • Kafka深度解析与实战应用
  • 流程设计实战:流程架构设计六步法
  • C++学习:六个月从基础到就业——面向对象编程:构造函数与析构函数
  • Java 中的各种锁详解
  • 【AAOS】【源码分析】Car UX Restrictions
  • Spring Boot中接入DeepSeek的流式输出
  • 鸿蒙应用(医院陪诊系统)开发篇1·主页面的tabs布局
  • 第 4 篇:Motion 拖拽与手势动画(交互篇)—— 打造直觉化交互体验
  • 芯片测试工具系统Demo示例
  • 探索鸿蒙沉浸式:打造无界交互体验
  • MVC协同工作流程
  • langchain框架-文档分割器详解(非官方库)
  • BTS7960 直流电机控制程序
  • 音视频之H.265/HEVC预测编码
  • 软考备考(一)学习笔记
  • ZYNQ系列SOC或FPGA常用核心电源方案选型
  • Node.js 的定义、用途、安装方法
  • 《Chronos: Learning the Language of Time Series》
  • Spring Cloud Gateway 的执行链路详解