go特性-数组与切片
数组:
复制传递(不要按照c/c++的方式去理解,c/c++中数组是引用传递),定长
切片:
引用传递,底层实现是3个字段 array(数组) + len(长度) +cap(容量)
type slice struct {
array unsafe.Pointer
len int
cap int
}
要特别注意的是,切片的引用传递指的是切片传递时,切片的array字段是引用传递的,len和cap字段依然是赋值传递。
写个伪代码:
Array []interface{}
Len int
Cap int
}
func fake() {
slice1 := &Slice{
Array: 指向一块连续内存的定长数组,
Len: 0,
Cap: 4
}
slice2 := slice1 // 这一行相当于如下:
slice2 := &Slice{}
slice2.Array = slice1.Array // 指向同一块内存,所以说切片是引用传递
slice2.Len = slice1.Len // len字段被复制了
slice2.Cap = slice2.Cap // cap字段被复制了
// 后续如果触发了任一slice的array重新分配内存,另一个slice都是不知道的
// 已经修改任一slice的len和cap,另一个slice也是不知道的
}
最后总结题:
/*
输出结果:
array1: [1 2 3] array2 [100 2 3]
slice1: [100 2 3] slice2 [100 2 3]
*/
func TestSlice1(t *testing.T) {
// 数组是赋值传递
array1 := [3]int{1,2,3}
// 这里array1复制了一份,array2和array1已经不是同一份数据了
// 所以对数组array1,array2的修改是互不影响的
array2 := array1
array2[0] = 100
fmt.Println("array1:", array1, "array2", array2)
// 切片是引用传递
slice1 := make([]int, 0)
slice1 = append(slice1, 1, 2, 3)
// slice2和slice1引用的同一份数据,所以slice2对已有元素的修改,会影响到slice1
// 这里有个细节需要注意,往下面TestSlice2继续看
slice2 := slice1
slice2[0] = 100
fmt.Println("slice1:", slice1, "slice2", slice2)
}
/*
输出结果
slice1: [1 2 3] slice2 [1 2 3 4]
slice1: [1 2 3] slice2 [1 2 3 4 5]
slice1: [1 2 3] slice2 [100 2 3 4 5]
*/
func TestSlice2(t *testing.T) {
// 切片是引用传递
slice1 := make([]int, 0, 4) // 容量是4
slice1 = append(slice1, 1, 2, 3)
// slice2和slice1引用的同一份数据,所以slice2对元素的修改,会影响到slice1
// 特别要注意的是,这里说的引用同一份数据,实际上是指的slice1和slice2内部的ptr指向了同一个数组
// 但是slice1和slice2结构中的len和cap是复制传递的
slice2 := slice1
// 添加第4个元素,容量足够,不会触发内部ptr数组重新分配
slice2 = append(slice2, 4)
fmt.Println("slice1:", slice1, "slice2", slice2)
// 添加第5个元素,容量不足,slice2.ptr重新分配内存,此时slice2.ptr和slice1.ptr已经不是同一份内存了
slice2 = append(slice2, 5)
fmt.Println("slice1:", slice1, "slice2", slice2)
// 所以这里slice2对已有元素的修改,不会影响到slice1了
slice2[0] = 100
fmt.Println("slice1:", slice1, "slice2", slice2)
}
```**------------恢复内容开始------------**
**数组:**
复制传递(不要按照c/c++的方式去理解,c/c++中数组是引用传递),定长
**切片:**
引用传递,底层实现是3个字段 array(数组) + len(长度) +cap(容量)
```go/src/runtime/slice.go slice结构定义:
type slice struct {
array unsafe.Pointer
len int
cap int
}
要特别注意的是,切片的引用传递指的是切片传递时,切片的array字段是引用传递的,len和cap字段依然是赋值传递。
写个伪代码:
Array []interface{}
Len int
Cap int
}
func fake() {
slice1 := &Slice{
Array: 指向一块连续内存的定长数组,
Len: 0,
Cap: 4
}
slice2 := slice1 // 这一行相当于如下:
slice2 := &Slice{}
slice2.Array = slice1.Array // 指向同一块内存,所以说切片是引用传递
slice2.Len = slice1.Len // len字段被复制了
slice2.Cap = slice2.Cap // cap字段被复制了
// 后续如果触发了任一slice的array重新分配内存,另一个slice都是不知道的
// 已经修改任一slice的len和cap,另一个slice也是不知道的
}
最后总结题:
/*
输出结果:
array1: [1 2 3] array2 [100 2 3]
slice1: [100 2 3] slice2 [100 2 3]
*/
func TestSlice1(t *testing.T) {
// 数组是赋值传递
array1 := [3]int{1,2,3}
// 这里array1复制了一份,array2和array1已经不是同一份数据了
// 所以对数组array1,array2的修改是互不影响的
array2 := array1
array2[0] = 100
fmt.Println("array1:", array1, "array2", array2)
// 切片是引用传递
slice1 := make([]int, 0)
slice1 = append(slice1, 1, 2, 3)
// slice2和slice1引用的同一份数据,所以slice2对已有元素的修改,会影响到slice1
// 这里有个细节需要注意,往下面TestSlice2继续看
slice2 := slice1
slice2[0] = 100
fmt.Println("slice1:", slice1, "slice2", slice2)
}
/*
输出结果
slice1: [1 2 3] slice2 [1 2 3 4]
slice1: [1 2 3] slice2 [1 2 3 4 5]
slice1: [1 2 3] slice2 [100 2 3 4 5]
*/
func TestSlice2(t *testing.T) {
// 切片是引用传递
slice1 := make([]int, 0, 4) // 容量是4
slice1 = append(slice1, 1, 2, 3)
// slice2和slice1引用的同一份数据,所以slice2对元素的修改,会影响到slice1
// 特别要注意的是,这里说的引用同一份数据,实际上是指的slice1和slice2内部的ptr指向了同一个数组
// 但是slice1和slice2结构中的len和cap是复制传递的
slice2 := slice1
// 添加第4个元素,容量足够,不会触发内部ptr数组重新分配
slice2 = append(slice2, 4)
fmt.Println("slice1:", slice1, "slice2", slice2)
// 添加第5个元素,容量不足,slice2.ptr重新分配内存,此时slice2.ptr和slice1.ptr已经不是同一份内存了
slice2 = append(slice2, 5)
fmt.Println("slice1:", slice1, "slice2", slice2)
// 所以这里slice2对已有元素的修改,不会影响到slice1了
slice2[0] = 100
fmt.Println("slice1:", slice1, "slice2", slice2)
}
------------恢复内容结束------------
go特性-数组与切片的更多相关文章
- Go语言--数组、切片、
3.1 数组--固定大小的连续空间 3.1.1 声明数组 写法 var 数组变量名 [元素数量]T 说明: 变量名就是使用时的变量 元素的数量可以是表达式,最后必须为整型数值 T 可是是任意基本类型, ...
- go语言之行--数组、切片、map
一.内置函数 append :追加元素到slice里,返回修改后的slice close :关闭channel delete :从map中删除key对应的value panic : 用于异常处理,停 ...
- 《Go语言实战》笔记之第四章 ----数组、切片、映射
原文地址: http://www.niu12.com/article/11 ####数组 数组是一个长度固定的数据类型,用于存储一段具有相同的类型的元素的连续块. 数组存储的类型可以是内置类型,如整型 ...
- Go语言入门——数组、切片和映射(下)
上篇主要介绍了Go语言里面常见的复合数据类型的声明和初始化. 这篇主要针对数组.切片和映射这些复合数据类型从其他几个方面介绍比较下. 1.遍历 不管是数组.切片还是映射结构,都是一种集合类型,要从这些 ...
- go 学习笔记之数组还是切片都没什么不一样
上篇文章中详细介绍了 Go 的基础语言,指出了 Go 和其他主流的编程语言的差异性,比较侧重于语法细节,相信只要稍加记忆就能轻松从已有的编程语言切换到 Go 语言的编程习惯中,尽管这种切换可能并不是特 ...
- PHP转Go系列:数组与切片
数组的定义 用过PHP的同学应该很清楚,无论多么复杂的数据格式都可以用数组来表达,什么类型的数据都可以往里塞,它是工作必备的一部分,使用很简单,易用程度简直变态. $array = [1, 'name ...
- go语言之字符串、指针、数组、切片、结构struct、面向对象
一: 字符串 概述: Go 语言将字符串作为 种原生的基本数据类型,字 符串的初始化可以使用字符串字面量. (1)字符串是常量,可以通过类 数组 索引访问其字节单元,但是不能修改某个字节的值 (2)宇 ...
- PHP转Go系列:数组与切片 转
数组的定义# 用过PHP的同学应该很清楚,无论多么复杂的数据格式都可以用数组来表达,什么类型的数据都可以往里塞,它是工作必备的一部分,使用很简单,易用程度简直变态. Copy $array = [1, ...
- GO语言总结(3)——数组和切片
上篇博文简单介绍了一下Go语言的基本类型——GO语言总结(2)——基本类型,本篇博文开始介绍Go语言的数组和切片. 一.数组 与其他大多数语言类似,Go语言的数组也是一个元素类型相同的定长的序列. ( ...
随机推荐
- day77:luffy:导航栏的实现&DjangoRestFramework JWT&多条件登录
目录 1.导航栏的实现 2.登录前戏:用户表初始化 3.DjangoRestFramework JWT 4.多条件登录 5.登录状态的判断和退出登录 1.导航栏的实现 1.设计导航栏的model模型类 ...
- eclipse之SSH配置spring【二】
第一篇中配置struts完成(http://www.cnblogs.com/dev2007/p/6475074.html),在此基础上,继续配置spring. web.xml中增加listener,依 ...
- Java踩坑记系列之Arrays.AsList
java.util.Arrays的asList方法可以方便的将数组转化为集合,我们平时开发在初始化ArrayList时使用的比较多,可以简化代码,但这个静态方法asList()有几个坑需要注意: 一. ...
- [论文解读] 阿里DIEN整体代码结构
[论文解读] 阿里DIEN整体代码结构 目录 [论文解读] 阿里DIEN整体代码结构 0x00 摘要 0x01 文件简介 0x02 总体架构 0x03 总体代码 0x04 模型基类 4.1 基本逻辑 ...
- python使用matplotlib画图,jieba分词、词云、selenuium、图片、音频、视频、文字识别、人脸识别
一.使用matplotlib画图 关注公众号"轻松学编程"了解更多. 使用matplotlib画柱形图 import matplotlib from matplotlib impo ...
- vscode 插件配置指北
Extension Manifest 就像 chrome 插件使用 manifest.json 来管理插件的配置一样,vscode 的插件也有一个 manifest,而且就叫 package.json ...
- C++函数四( 具有默认参数值的函数)
在C++语言中,可以设置函数形参的默认值,在调用函数时,若明确给出了实参的值,则使用相应实参的值;若没有给出相应实参的值,则使用默认的值.这将为函数调用带来方便和灵活. [示例] #include&l ...
- 自定义MFC对话窗口的类名
默认情况下,MFC对话框的窗口类名为"#32770",如果想自定义窗口类名呢,需要两步: 1.修改rc文件 这一步需要直接编辑rc文件,使用任意记事本工具即可,找到窗口的相关定义, ...
- 深入Python中的正则表达式
正则表达式应用的场景也非常多.常见的比如:搜索引擎的搜索.爬虫结果的匹配.文本数据的提取等等都会用到,所以掌握甚至精通正则表达式是一个硬性技能,非常必要. 正则表达式 正则表达式是一个特殊的字符序列, ...
- Core WebApi项目快速入门(三):踩坑笔记
目前做公司一个项目,遇到了一些坑.跟大家分享,避免再次采坑. 1. 服务端发布应用报错 在windows server上发布程序报错.系统缺少更新包. https://support.microsof ...