详解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 语言描述)
原文地址 ? 传送门 线性回归 线性回归是一种较为简单,但十分重要的机器学习方法.掌握线性的原理及求解方法,是深入了解线性回归的基本要求.除此之外,线性回归也是监督学习回归部分的基石. 线性回归介绍 ...
随机推荐
- 基于Grafana的Repeate Panel快速定义面板
Grafana提供的Repeate Panel功能,可以快速定义一类相同的面板. 一.定义模板变量 点击"设置"."模板",如下所示: 设置模板变量名称.类型. ...
- WebApp开发总结
WebApp开发总结 框架的使用网络上都有教程,就不写了,主要记录下个人的开发总结以方便以后开发注意. css公用样式统一定义 css样式抽出复用 appearance: none; 取消系统默认样式 ...
- MySQL GROUP BY多个字段分组用法详解
mysql语句中group by 很容易理解 是分组查询.比如 select sum(score) from user group by name 意思是查询每个人的分数总和但是, select su ...
- Brackets 1.8 开源+免费的Web前端网页文本编辑工具
Brackets 1.8 开源+免费的Web网页文本编辑工具 -------------->> ---------------------- A modern, open source ...
- WeQuant比特币交易策略回测记录
程序参数 PARAMS = { "start_time": "2017-02-01 00:00:00", "end_time": " ...
- node中package.json全方面解析
Name 必须字段. 小提示: 不要在name中包含js, node字样: 这个名字最终会是URL的一部分,命令行的参数,目录名,所以不能以点号或下划线开头: 这个名字可能在require()方法中被 ...
- JQuery基础 接下来我将把我最近学习jQuery所做的笔记发布,希望对初学者有些许帮助,也方便自己以后复习
jQuery简介 1.概念: jQuery是一个优秀的JavaScript库,而非JavaScript.它是轻量级的库2.兼容性:兼容css3,以及各种浏览器.3版本: 1.x-----------兼 ...
- python -- 装饰器的高级应用
装饰器和装饰器模式装饰器模式是面向对象的一种设计模式,支持将行为动态增加到已经存在的对象上.当装饰一个对象的时候,就表示独立与其他类实例对象,为该对象扩展了新的功能. python的装饰器不是装饰器模 ...
- python+selenium自动化软件测试(第2章):WebDriver API
2.1 操作元素基本方法 前言前面已经把环境搭建好了,从这篇开始,正式学习selenium的webdriver框架.我们平常说的 selenium自动化,其实它并不是类似于QTP之类的有GUI界面的可 ...
- 归并排序—Java版
一开始做算法的时候,感觉递归算法很绕,所以我就在阅读别人代码的基础上,对代码每一步都添加自己的注解,方便我以后的学习. public class MergeSort { /** * 归并排序 * @p ...