数组:

复制传递(不要按照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特性-数组与切片的更多相关文章

  1. Go语言--数组、切片、

    3.1 数组--固定大小的连续空间 3.1.1 声明数组 写法 var 数组变量名 [元素数量]T 说明: 变量名就是使用时的变量 元素的数量可以是表达式,最后必须为整型数值 T 可是是任意基本类型, ...

  2. go语言之行--数组、切片、map

    一.内置函数 append :追加元素到slice里,返回修改后的slice close :关闭channel delete :从map中删除key对应的value panic  : 用于异常处理,停 ...

  3. 《Go语言实战》笔记之第四章 ----数组、切片、映射

    原文地址: http://www.niu12.com/article/11 ####数组 数组是一个长度固定的数据类型,用于存储一段具有相同的类型的元素的连续块. 数组存储的类型可以是内置类型,如整型 ...

  4. Go语言入门——数组、切片和映射(下)

    上篇主要介绍了Go语言里面常见的复合数据类型的声明和初始化. 这篇主要针对数组.切片和映射这些复合数据类型从其他几个方面介绍比较下. 1.遍历 不管是数组.切片还是映射结构,都是一种集合类型,要从这些 ...

  5. go 学习笔记之数组还是切片都没什么不一样

    上篇文章中详细介绍了 Go 的基础语言,指出了 Go 和其他主流的编程语言的差异性,比较侧重于语法细节,相信只要稍加记忆就能轻松从已有的编程语言切换到 Go 语言的编程习惯中,尽管这种切换可能并不是特 ...

  6. PHP转Go系列:数组与切片

    数组的定义 用过PHP的同学应该很清楚,无论多么复杂的数据格式都可以用数组来表达,什么类型的数据都可以往里塞,它是工作必备的一部分,使用很简单,易用程度简直变态. $array = [1, 'name ...

  7. go语言之字符串、指针、数组、切片、结构struct、面向对象

    一: 字符串 概述: Go 语言将字符串作为 种原生的基本数据类型,字 符串的初始化可以使用字符串字面量. (1)字符串是常量,可以通过类 数组 索引访问其字节单元,但是不能修改某个字节的值 (2)宇 ...

  8. PHP转Go系列:数组与切片 转

    数组的定义# 用过PHP的同学应该很清楚,无论多么复杂的数据格式都可以用数组来表达,什么类型的数据都可以往里塞,它是工作必备的一部分,使用很简单,易用程度简直变态. Copy $array = [1, ...

  9. GO语言总结(3)——数组和切片

    上篇博文简单介绍了一下Go语言的基本类型——GO语言总结(2)——基本类型,本篇博文开始介绍Go语言的数组和切片. 一.数组 与其他大多数语言类似,Go语言的数组也是一个元素类型相同的定长的序列. ( ...

随机推荐

  1. 编写优美代码的七条规范(Python版)

    编程是一种与计算机系统通信的语言.交流就是与某人分享思想.二进制语言是计算机的最核心的语言.但是在前端,我们有很多种语言.这些语言使用解释器将前端代码转换为二进制代码.基本上,系统对一行代码执行大量内 ...

  2. 基于ArcGIS ModelBuilder的GDB批量分区裁剪——可保留原始GDB要素集要素类结构

    文章版权由作者pxtgis和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/pxtgis/. 一.概述 在数据处理工作中经常遇到批量裁剪ArcGIS文件地理数据库( ...

  3. CodeForces 1420E Battle Lemmings

    题意 略. \(\texttt{Data Range:}1\leq n\leq 80\) 题解 首先考虑初始状态怎么算答案.很明显直接数满足的不好数,用总的减去不满足的还比较好做.注意到所有不满足的是 ...

  4. MySQL图形界面客户端

    图形界面客户端 使用图形界面客户端操作数据库更直观.方便.下面三个客户端都能操作MySQL,各有各自的优点. 1.Navicat Premium 下载安装包下载 关注公众号[轻松学编程],然后回复[n ...

  5. NoSQL非关系型数据库

    NoSQL 关注公众号"轻松学编程"了解更多. 一.概念 NoSQL(Not Only SQL)非关系型数据库(功能换效率). 优点 开发维护成本低 访问灵活 访问速度快(缓存+快 ...

  6. Mybatis 批量更新遇到的小问题

    小问题 记一个开发过程中因为小细节的遗漏而引发的 "莫名其妙",公司中有个2B(to B)供应链项目,持久层用的是 JPA,这里我就不吐槽 JPA 了,这种 SQL 嵌入在代码里的 ...

  7. Oracle数据库系统结构(一) 

    1.Oracle数据库系统结构概述 Oracle数据库由存放在磁盘上的数据库(DB)和对磁盘上的数据库进行管理的数据库管理系统(DBMS)两部分构成,分别对应着数据库的存储结构和软件结构. Oracl ...

  8. 4. Spark在集群上运行

    *以下内容由<Spark快速大数据分析>整理所得. 读书笔记的第四部分是讲的是Spark在集群上运行的知识点. 一.Spark应用组件介绍 二.Spark在集群运行过程 三.Spark配置 ...

  9. putty连接Linux(NAT)

    1.系统装好后第一次连的时候需要打开ssh服务 sudo apt-get install openssh-server 当在机器不能通过ping ip相通的话那么就要解决ip不同的问题,当ip相通还是 ...

  10. Ubuntu linux系统下 su:出现: authentication failure的解决办法

    当出现这个问题后,尝试一下方法: $ sudo passwd rootEnter new UNIX password://此时输入你的密码Retype new UNIX password://再次输入 ...