上一篇  详解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 【二】的更多相关文章

  1. 详解go语言的array和slice 【一】

    本篇会详细讲解go语言中的array和slice,和平时开发中使用他样时需要注意的地方,以免入坑. Go语言中array是一组定长的同类型数据集合,并且是连续分配内存空间的. 声明一个数组 var a ...

  2. 详解 Go 语言中的 time.Duration 类型

    swardsman详解 Go 语言中的 time.Duration 类型swardsman · 2018-03-17 23:10:54 · 5448 次点击 · 预计阅读时间 5 分钟 · 31分钟之 ...

  3. 详解Go语言调度循环源码实现

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客: https://www.luozhiyun.com/archives/448 本文使用的go的源码15.7 概述 提到"调度&q ...

  4. 【详解】ThreadPoolExecutor源码阅读(二)

    系列目录 [详解]ThreadPoolExecutor源码阅读(一) [详解]ThreadPoolExecutor源码阅读(二) [详解]ThreadPoolExecutor源码阅读(三) AQS在W ...

  5. 详解Javascript中的Array对象

    基础介绍 创建数组 和Object对象一样,创建Array也有2种方式:构造函数.字面量法. 构造函数创建 使用构造函数的方式可以通过new关键字来声明,如下所示: 12 var arr = new ...

  6. Rserve详解,R语言客户端RSclient【转】

    R语言服务器程序 Rserve详解 http://blog.fens.me/r-rserve-server/ Rserve的R语言客户端RSclient https://blog.csdn.net/u ...

  7. Linux进程上下文切换过程context_switch详解--Linux进程的管理与调度(二十一)

    1 前景回顾 1.1 Linux的调度器组成 2个调度器 可以用两种方法来激活调度 一种是直接的, 比如进程打算睡眠或出于其他原因放弃CPU 另一种是通过周期性的机制, 以固定的频率运行, 不时的检测 ...

  8. 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 ...

  9. 机器学习|线性回归算法详解 (Python 语言描述)

    原文地址 ? 传送门 线性回归 线性回归是一种较为简单,但十分重要的机器学习方法.掌握线性的原理及求解方法,是深入了解线性回归的基本要求.除此之外,线性回归也是监督学习回归部分的基石. 线性回归介绍 ...

随机推荐

  1. 基于Grafana的Repeate Panel快速定义面板

    Grafana提供的Repeate Panel功能,可以快速定义一类相同的面板. 一.定义模板变量 点击"设置"."模板",如下所示: 设置模板变量名称.类型. ...

  2. WebApp开发总结

    WebApp开发总结 框架的使用网络上都有教程,就不写了,主要记录下个人的开发总结以方便以后开发注意. css公用样式统一定义 css样式抽出复用 appearance: none; 取消系统默认样式 ...

  3. MySQL GROUP BY多个字段分组用法详解

    mysql语句中group by 很容易理解 是分组查询.比如 select sum(score) from user group by name 意思是查询每个人的分数总和但是, select su ...

  4. Brackets 1.8 开源+免费的Web前端网页文本编辑工具

    Brackets 1.8 开源+免费的Web网页文本编辑工具   -------------->> ---------------------- A modern, open source ...

  5. WeQuant比特币交易策略回测记录

    程序参数 PARAMS = { "start_time": "2017-02-01 00:00:00", "end_time": " ...

  6. node中package.json全方面解析

    Name 必须字段. 小提示: 不要在name中包含js, node字样: 这个名字最终会是URL的一部分,命令行的参数,目录名,所以不能以点号或下划线开头: 这个名字可能在require()方法中被 ...

  7. JQuery基础 接下来我将把我最近学习jQuery所做的笔记发布,希望对初学者有些许帮助,也方便自己以后复习

    jQuery简介 1.概念: jQuery是一个优秀的JavaScript库,而非JavaScript.它是轻量级的库2.兼容性:兼容css3,以及各种浏览器.3版本: 1.x-----------兼 ...

  8. python -- 装饰器的高级应用

    装饰器和装饰器模式装饰器模式是面向对象的一种设计模式,支持将行为动态增加到已经存在的对象上.当装饰一个对象的时候,就表示独立与其他类实例对象,为该对象扩展了新的功能. python的装饰器不是装饰器模 ...

  9. python+selenium自动化软件测试(第2章):WebDriver API

    2.1 操作元素基本方法 前言前面已经把环境搭建好了,从这篇开始,正式学习selenium的webdriver框架.我们平常说的 selenium自动化,其实它并不是类似于QTP之类的有GUI界面的可 ...

  10. 归并排序—Java版

    一开始做算法的时候,感觉递归算法很绕,所以我就在阅读别人代码的基础上,对代码每一步都添加自己的注解,方便我以后的学习. public class MergeSort { /** * 归并排序 * @p ...