详解go语言的array和slice 【二】
上一篇 详解go语言的array和slice 【一】已经讲解过,array和slice的一些基本用法,使用array和slice时需要注意的地方,特别是slice需要注意的地方比较多。上一篇的最后讲解到创建新的slice时使用第三个索引来限制slice的容量,在操作新slice时,如果新slice的容量大于长度时,添加新元素依然后使源的相应元素改变。这一篇里我会讲解到如何避免这些问题,以及迭代、和做为方法参数方面的知识点。
slice的长度和容量设置为同一个值
如果在创建新的slice时我们把他的长度和容量的值设置为样的值,那么在append新元素时,底层会创建一个新的array并把之前的值复制过去。这样就不会影响之前共同的底层array了。
// 创建一个容量和长度均为6的slice
slice1 := []int{, , , , , }
// 对slices1进行切片,长度为2容量为3
slice2 := slice1[::]
fmt.Println("cap", cap(slice2))
fmt.Println("slice2", slice2) //修改一个共同指向的元素
//两个slice的值都会修改
slice2[] =
fmt.Println("slice1", slice1)
fmt.Println("slice2", slice2) // 增加一个元素
slice2 = append(slice2, ) fmt.Println("slice1: ", slice1)
fmt.Println("slice2: ", slice2)
输出结果
cap
slice2 [ ]
slice1 [ ]
slice2 [ ]
slice1: [ ]
slice2: [ ]
代码中的长度和容量是一样的,长度和容量的计算公式看我的上一篇博客。增加一个元素后,原来共同指向的底层数据是没有变的。因为slice2的底层array被重新赋值了。
迭代slice
go语言内置一个关键字range用于迭代集合,当然他也可以迭代slice,也可以使用 _ 来忽略我们不关心的元素,但是如果只关心index则不需这么写 for index,_ := range slice1。下在给出完整代码
// 创建一个容量和长度均为6的slice
slice1 := []int{, , , , , } for index, value := range slice1 {
fmt.Println("index: ", index, " value: ", value)
} // 可以忽略我们不关心的元素
// 只关心value
for _, value := range slice1 {
fmt.Println("value ", value)
} // 只关心index, 可以不用 _
for index := range slice1 {
fmt.Println("index: ", index)
}
需要注意的是range 迭代的value值并不是一个复本,我们可以对比一下迭代的value和原slice内相应index下value的地址:
// 创建一个容量和长度均为6的slice
slice1 := []int{, , , , , } for index, value := range slice1 {
fmt.Println("index: ", index, " value address : ", &value, " slice1 value address", &slice1[index]) }
输出结果
index: value address : 0xc04204e088 slice1 value address 0xc04206a030
index: value address : 0xc04204e088 slice1 value address 0xc04206a038
index: value address : 0xc04204e088 slice1 value address 0xc04206a040
index: value address : 0xc04204e088 slice1 value address 0xc04206a048
index: value address : 0xc04204e088 slice1 value address 0xc04206a050
index: value address : 0xc04204e088 slice1 value address 0xc04206a058
slice1中value的地址是不断变化的。而迭代的value值的地址没有变化,这是因为value是一个变量,每次迭代的时候赋不同的值。我们把代码写成下面这样,你就清楚了
var index, value int
for index, value = range slice1 {
fmt.Println("index: ", index, &index, " value address : ", &value, " slice1 value address", &slice1[index]) }
除了使用range 也可以使用传统的for循环来做迭代
slice1 := []int{, , , , , }
for i, len := , len(slice1); i < len; i++ {
fmt.Println("index: ", i, " value:", slice1[i])
}
slice作为方法参数
由于slice的特殊结构,有一个指针指向一个数组
s := make([]int, , )
fmt.Println("len: ", len(s))
fmt.Println("cap: ", cap(s))
s = append(s, ) s[] =

所以,slice做为方法的参数传递时,只会复制slice本身而不会复制slice底层的array.如果我们创建一个int类型有100万长度的slice ,把他传递给一个方法时,只需要复制24个字节就够了。指针需要8个,长度和容量都是8个。
const size int = *
func main() {
slice0 := make([]int, size)
fmt.Println("slice0 len: ", len(slice0), " cap :", cap(slice0))
doSomeThing(slice0)
}
func doSomeThing(s []int) {
fmt.Println(len(s))
}

详解go语言的array和slice 【二】的更多相关文章
- 详解go语言的array和slice 【一】
本篇会详细讲解go语言中的array和slice,和平时开发中使用他样时需要注意的地方,以免入坑. Go语言中array是一组定长的同类型数据集合,并且是连续分配内存空间的. 声明一个数组 var a ...
- 详解 Go 语言中的 time.Duration 类型
swardsman详解 Go 语言中的 time.Duration 类型swardsman · 2018-03-17 23:10:54 · 5448 次点击 · 预计阅读时间 5 分钟 · 31分钟之 ...
- 详解Go语言调度循环源码实现
转载请声明出处哦~,本篇文章发布于luozhiyun的博客: https://www.luozhiyun.com/archives/448 本文使用的go的源码15.7 概述 提到"调度&q ...
- 【详解】ThreadPoolExecutor源码阅读(二)
系列目录 [详解]ThreadPoolExecutor源码阅读(一) [详解]ThreadPoolExecutor源码阅读(二) [详解]ThreadPoolExecutor源码阅读(三) AQS在W ...
- 详解Javascript中的Array对象
基础介绍 创建数组 和Object对象一样,创建Array也有2种方式:构造函数.字面量法. 构造函数创建 使用构造函数的方式可以通过new关键字来声明,如下所示: 12 var arr = new ...
- Rserve详解,R语言客户端RSclient【转】
R语言服务器程序 Rserve详解 http://blog.fens.me/r-rserve-server/ Rserve的R语言客户端RSclient https://blog.csdn.net/u ...
- Linux进程上下文切换过程context_switch详解--Linux进程的管理与调度(二十一)
1 前景回顾 1.1 Linux的调度器组成 2个调度器 可以用两种方法来激活调度 一种是直接的, 比如进程打算睡眠或出于其他原因放弃CPU 另一种是通过周期性的机制, 以固定的频率运行, 不时的检测 ...
- LeetCode刷题 1. Two Sum 两数之和 详解 C++语言实现 java语言实现
1. Two Sum 两数之和 Given an array of integers, return indices of the two numbers such that they add up ...
- 机器学习|线性回归算法详解 (Python 语言描述)
原文地址 ? 传送门 线性回归 线性回归是一种较为简单,但十分重要的机器学习方法.掌握线性的原理及求解方法,是深入了解线性回归的基本要求.除此之外,线性回归也是监督学习回归部分的基石. 线性回归介绍 ...
随机推荐
- AT24C02使用详解
---恢复内容开始--- 这篇文章是写给一个学弟看的,关于IIC,关于24C02的单字节写入\读取..页写入和读取,,学弟总是害怕协议,,,我总是对人家说,本来就这样的,协议就是人家这样规定的,,,如 ...
- tensorflow笔记(四)之MNIST手写识别系列一
tensorflow笔记(四)之MNIST手写识别系列一 版权声明:本文为博主原创文章,转载请指明转载地址 http://www.cnblogs.com/fydeblog/p/7436310.html ...
- Windows8.1 与Ubuntu14.04双系统
机型:联想 Y480 现有操作系统:win8.1 64位 物理内存:8G 磁盘存储:两个硬盘 1. SSD为固态盘 Solid State Drives 110G 现已安装有win8系统 2.H ...
- mysql事件机制——定时任务
定时任务是老生常谈了,因为我们总是需要定时修改特定的数据. 实现它的方法肯定不止一种,但我在相当长一段时间里都是用程序编码去做的,今天突然想到“为什么一定要采用调用的方式?”,用数据库自身的能力去实现 ...
- Amazon Aurora解读(SIGMOD 2017)
Amazon在SIGMOD 2017发表了论文<Amazon Aurora: DesignConsiderations for High Throughput Cloud-Native Rela ...
- INotifyPropertyChanged(监听数据),当数据改变时调用
public class BaseViewModel : INotifyPropertyChanged { public event PropertyChangedEventHan ...
- jmeter性能测试 套路二
1.一般我们不会通过下面这种去跑性能测试 2.我们会通过这种方式去跑性能测试 3.录制自动化 就用新的 4.录制性能测试 就用
- CSS基础用法
[CSS常用选择器] 标签选择器 写法: HTML标签名{}作用: 可以选中页面中,所有与选择器同名的HTML标签. 类选择器(class选择器)写法: .class名{}调用: 在需要调用选择器样式 ...
- BZOJ 3379: [Usaco2004 Open]Turning in Homework 交作业
Description 贝茜有C(1≤C≤1000)门科目的作业要上交,之后她要去坐巴士和奶牛同学回家. 每门科目的老师所在的教室排列在一条长为H(1≤H≤1000)的走廊上,他们只在课后接收 ...
- (一)Builder(建造者)模式
我们一般在构建javabean的对象的时候通常有三种写法: 1.直接通过构造函数传参的方式设置属性,这种方法如果属性过多的话会让构造函数十分臃肿,而且不能灵活的选择只设置某些参数. 2.采用重叠构造区 ...