golang学习笔记 ---slice
- 指向底层数组的指针
- slice目前使用到的底层数组的元素个数,即长度
- 底层数组的最大长度,即容量
因此当我们定义一个切片变量,s := make([]int, 5, 10),即为指向了一个最大长度为10的底层数组,目前切片s使用到的长度为5。
基于slice的定义,在使用slice时,有以下几点注意事项:
- 当从左边界有截断时,会改变新切片容量大小
- 左边界默认0,最小为0;右边界默认slice的长度,最大为slice的容量
- 当然,因为指向同一个底层数组,对新slice的操作会影响到原来的slice
package main import (
"fmt"
) func main() { a := make([]int, 5, 10) b := a[:3]
//b len: 3 cap: 10
fmt.Println("b-- ", "len:", len(b), " ,cap:", cap(b)) //当从左边界有截断时 会改变新切片容量大小
c := a[2:4]
//c len: 2 cap: 8
fmt.Println("c-- ", "len:", len(c), " ,cap:", cap(c)) //左边界默认0 最小为0 | 右边界默认slice的长度 最大为slice的容量
d := a[:cap(a)]
//d len: 10 cap: 10
fmt.Println("d-- ", "len:", len(d), " ,cap:", cap(d))
}
输出:
b-- len: 3 ,cap: 10
c-- len: 2 ,cap: 8
d-- len: 10 ,cap: 10
2.slice的赋值及函数间传递
a := []int{1, 2, 3, 4, 5}
b := a
package main import (
"fmt"
) func main() { a := []int{1, 2, 3, 4, 5}
b := a //对b进行操作会影响到a
b[0] = 10
// 10 2 3 4 5
fmt.Println(a)
}
输出:
[10 2 3 4 5]
如上所示,则a, b指向同一个底层数组,且长度及容量因素相同,对b进行的操作会影响到a。
切片作为函数参数示例:
package main import (
"fmt"
) func modifySlice(s []int) {
s[0] = 10
} func main() {
a := []int{1, 2, 3, 4, 5}
modifySlice(a)
//[10 2 3 4 5]
fmt.Println(a)
}
输出:
[10 2 3 4 5]
如上所示,将slice作为参数在函数间传递的时候是值传递,产生了一个新的slice,只不过新的slice仍然指向原来的底层数组,所以通过新的slice也能改变原来的slice的值
package main import (
"fmt"
) func modifySlice(s []int) {
s = []int{10, 20, 30, 40, 50}
s[0] = -1
}
func main() {
a := []int{1, 2, 3, 4, 5}
modifySlice(a)
//[1 2 3 4 5]
fmt.Println(a)
}
如上所示,在调用函数的内部,将s整体赋值一个新的slice,并不会改变a的值,因为modifySlice函数内对s重新的整体赋值,让s指向了一个新的底层数组,而不是传递进来之前的a指向的那个数组,之后s的任何操作都不会影响到a了。
3.slice的append操作
func append(s []T, x ...T) []T
package main import (
"fmt"
) func main() {
a := make([]int, 2, 4)
fmt.Println("initialize.....")
fmt.Println("a:", a, " &a[0]:", &a[0], " len:", len(a), " cap:", cap(a)) //通常append操作都是将返回值赋值给自己,
//此处为了方便说明,没有这样做 //改变b的前2个元素值 会影响到a
a[0] = 99
fmt.Println("赋值之后.....")
fmt.Println("a:", a, " &a[0]:", &a[0], " len:", len(a), " cap:", cap(a))
fmt.Println("Append之后.....")
b := append(a, 2)
b[0] = 1
fmt.Println("a:", a, " &a[0]:", &a[0], " len:", len(a), " cap:", cap(a))
fmt.Println("b:", b, " &b[0]:", &b[0], " len:", len(b), " cap:", cap(b)) a = append(a, 3)
fmt.Println("a Append之后.....")
fmt.Println("a:", a, " &a[0]:", &a[0], " len:", len(a), " cap:", cap(a))
fmt.Println("b:", b, " &b[0]:", &b[0], " len:", len(b), " cap:", cap(b)) a = append(a, 4)
a = append(a, 5) fmt.Println("a 再次Append之后.....")
//a 扩容了,指向不同的底层数组
fmt.Println("a:", a, " &a[0]:", &a[0], " len:", len(a), " cap:", cap(a))
//a的扩容没有影响到b,b还是指向原来的底层数组
fmt.Println("b:", b, " &b[0]:", &b[0], " len:", len(b), " cap:", cap(b))
}
输出:
initialize.....
a: [0 0] &a[0]: 0xc0000105a0 len: 2 cap: 4
赋值之后.....
a: [99 0] &a[0]: 0xc0000105a0 len: 2 cap: 4
Append之后.....
a: [1 0] &a[0]: 0xc0000105a0 len: 2 cap: 4
b: [1 0 2] &b[0]: 0xc0000105a0 len: 3 cap: 4
a Append之后.....
a: [1 0 3] &a[0]: 0xc0000105a0 len: 3 cap: 4
b: [1 0 3] &b[0]: 0xc0000105a0 len: 3 cap: 4
a 再次Append之后.....
a: [1 0 3 4 5] &a[0]: 0xc000014240 len: 5 cap: 8
b: [1 0 3] &b[0]: 0xc0000105a0 len: 3 cap: 4
a 再次Append之后,a 扩容了,指向不同的底层数组,a的扩容没有影响到b,b还是指向原来的底层数组
package main import (
"fmt"
) func main() {
a := make([]int, 2, 4)
a[0] = 10
a[1] = 20
//a: [10 20] &a[0]: 0x10410020 len: 2 cap: 4
fmt.Println("a:", a, " &a[0]:", &a[0], " len:", len(a), " cap:", cap(a)) //进行append操作
b := append(a[:1], 1) //a: [10 1] &a[0]: 0x10410020 len: 2 cap: 4
fmt.Println("a:", a, " &a[0]:", &a[0], " len:", len(a), " cap:", cap(a)) //b: [10 1] &b[0]: 0x10410020 len: 2 cap: 4
fmt.Println("b:", b, " &b[0]:", &b[0], " len:", len(b), " cap:", cap(b))
}
输出:
a: [10 20] &a[0]: 0xc0000105a0 len: 2 cap: 4
a: [10 1] &a[0]: 0xc0000105a0 len: 2 cap: 4
b: [10 1] &b[0]: 0xc0000105a0 len: 2 cap: 4
package main import (
"fmt"
) func main() {
a := make([]int, 2, 4)
a[0] = 10
a[1] = 20
//a: [10 20] &a[0]: 0x10410020 len: 2 cap: 4
fmt.Println("a:", a, " &a[0]:", &a[0], " len:", len(a), " cap:", cap(a)) //进行append操作
//b := append(a[:1], 1)
c := a[:1]
fmt.Println("c:", c, " &c[0]:", &c[0], " len:", len(c), " cap:", cap(c))
b := append(c, 1) //a: [10 1] &a[0]: 0x10410020 len: 2 cap: 4
fmt.Println("a:", a, " &a[0]:", &a[0], " len:", len(a), " cap:", cap(a)) //b: [10 1] &b[0]: 0x10410020 len: 2 cap: 4
fmt.Println("b:", b, " &b[0]:", &b[0], " len:", len(b), " cap:", cap(b))
}
输出:
a: [10 20] &a[0]: 0xc000072140 len: 2 cap: 4
c: [10] &c[0]: 0xc000072140 len: 1 cap: 4
a: [10 1] &a[0]: 0xc000072140 len: 2 cap: 4
b: [10 1] &b[0]: 0xc000072140 len: 2 cap: 4
package main import (
"fmt"
) func main() { a := make([]int, 2, 4)
a[0] = 10
a[1] = 20
//a: [10 20] &a[0]: 0x10410020 len: 2 cap: 4
fmt.Println("a:", a, " &a[0]:", &a[0], " len:", len(a), " cap:", cap(a)) //进行append操作
//append是在第一个元素后开始追加,所以要超过容量,至少要追加4个,而不是之前例子的3个
b := append(a[:1], 1, 2, 3, 4) //a: [10 20] &a[0]: 0x10410020 len: 2 cap: 4
fmt.Println("a:", a, " &a[0]:", &a[0], " len:", len(a), " cap:", cap(a)) //b: [10 1 2 3 4] &b[0]: 0x10454020 len: 5 cap: 8
fmt.Println("b:", b, " &b[0]:", &b[0], " len:", len(b), " cap:", cap(b))
}
如果append的元素数较多,超过了原来的容量,直接采用了新的底层数组,也就不会影响到a了。
输出:
a: [10 20] &a[0]: 0xc0000105a0 len: 2 cap: 4
a: [10 20] &a[0]: 0xc0000105a0 len: 2 cap: 4
b: [10 1 2 3 4] &b[0]: 0xc000014240 len: 5 cap: 8
package main import (
"fmt"
) func testAppend(s []int) {
//进行append操作
s = append(s, 1)
//s: [10 1] &s[0]: 0x10410020 len: 2 cap: 4
fmt.Println("s:", s, " &s[0]:", &s[0], " len:", len(s), " cap:", cap(s))
}
func main() { a := make([]int, 2, 4)
a[0] = 10
a[1] = 20
//a: [10 20] &a[0]: 0x10410020 len: 2 cap: 4
fmt.Println("a:", a, " &a[0]:", &a[0], " len:", len(a), " cap:", cap(a)) testAppend(a[:1]) //a: [10 1] &a[0]: 0x10410020 len: 2 cap: 4
fmt.Println("a:", a, " &a[0]:", &a[0], " len:", len(a), " cap:", cap(a)) }
输出:
a: [10 20] &a[0]: 0xc0000105a0 len: 2 cap: 4
s: [10 1] &s[0]: 0xc0000105a0 len: 2 cap: 4
a: [10 1] &a[0]: 0xc0000105a0 len: 2 cap: 4
import (
"fmt"
) func testAppend(s []int) {
//进行append操作
s = append(s, 1, 2, 3, 4)
//s: [10 1] &s[0]: 0x10410020 len: 2 cap: 4
fmt.Println("s:", s, " &s[0]:", &s[0], " len:", len(s), " cap:", cap(s))
}
func main() { a := make([]int, 2, 4)
a[0] = 10
a[1] = 20
//a: [10 20] &a[0]: 0x10410020 len: 2 cap: 4
fmt.Println("a:", a, " &a[0]:", &a[0], " len:", len(a), " cap:", cap(a)) testAppend(a[:1]) //a: [10 1] &a[0]: 0x10410020 len: 2 cap: 4
fmt.Println("a:", a, " &a[0]:", &a[0], " len:", len(a), " cap:", cap(a)) }
输出
a: [10 20] &a[0]: 0xc0000105a0 len: 2 cap: 4 s: [10 1 2 3 4] &s[0]: 0xc000014240 len: 5 cap: 8 a: [10 20] &a[0]: 0xc0000105a0 len: 2 cap: 4
参考:
golang学习笔记 ---slice的更多相关文章
- golang学习笔记20 一道考察对并发多协程操作一个共享变量的面试题
golang学习笔记20 一道考察对并发多协程操作一个共享变量的面试题 下面这个程序运行的能num结果是什么? package main import ( "fmt" " ...
- golang学习笔记19 用Golang实现以太坊代币转账
golang学习笔记19 用Golang实现以太坊代币转账 在以太坊区块链中,我们称代币为Token,是以太坊区块链中每个人都可以任意发行的数字资产.并且它必须是遵循erc20标准的,至于erc20标 ...
- golang学习笔记18 用go语言编写移动端sdk和app开发gomobile
golang学习笔记18 用go语言编写移动端sdk和app开发gomobile gomobile的使用-用go语言编写移动端sdk和app开发https://blog.csdn.net/u01249 ...
- golang学习笔记17 爬虫技术路线图,python,java,nodejs,go语言,scrapy主流框架介绍
golang学习笔记17 爬虫技术路线图,python,java,nodejs,go语言,scrapy主流框架介绍 go语言爬虫框架:gocolly/colly,goquery,colly,chrom ...
- golang学习笔记16 beego orm 数据库操作
golang学习笔记16 beego orm 数据库操作 beego ORM 是一个强大的 Go 语言 ORM 框架.她的灵感主要来自 Django ORM 和 SQLAlchemy. 目前该框架仍处 ...
- golang学习笔记14 golang substring 截取字符串
golang学习笔记14 golang substring 截取字符串golang 没有java那样的substring函数,但支持直接根据 index 截取字符串mystr := "hel ...
- golang学习笔记13 Golang 类型转换整理 go语言string、int、int64、float64、complex 互相转换
golang学习笔记13 Golang 类型转换整理 go语言string.int.int64.float64.complex 互相转换 #string到intint,err:=strconv.Ato ...
- golang学习笔记12 beego table name `xxx` repeat register, must be unique 错误问题
golang学习笔记12 beego table name `xxx` repeat register, must be unique 错误问题 今天测试了重新建一个项目生成新的表,然后复制到旧的项目 ...
- golang学习笔记11 golang要用jetbrain的golang这个IDE工具开发才好
golang学习笔记11 golang要用jetbrain的golang这个IDE工具开发才好 jetbrain家的全套ide都很好用,一定要dark背景风格才装B 从File-->s ...
随机推荐
- 前端vue项目js中怎么保证链式调用后台接口
在一个for循环中对同一接口调用多次,如何保证逐步执行,同步执行. html部分 <DcFileUpload v-for="(item, index) of fileLengthLis ...
- vue学习指南:第六篇(详细) - Vue的组件 component
1. 什么是组件?有两种解释 1. 第一种解释: 什么是组件? 1. 组件是 vue 中的一个可复用的实例,所以new Vue() 是vue中最大的那个组件(根组件),有名字,使用的时候以单标签或双标 ...
- LeetCode237-Delete_Node_In_A_Linked_List
delete-node-in-a-linked-list public void deleteNode(ListNode node) { node.val = node.next.val; node. ...
- ASP.NET开发实战——(二)为什么使用ASP.NET
本文主要内容是通过分析<博客系统>需求,确定使用Web应用的形式来开发,然后介绍了HTML.HTTP的概念,并使用IIS搭建了一个静态的HTML“页面”,从而引出“动态”的ASP.NET. ...
- treegrid 表格树
treegrid 实现表格树的结构 效果图: 第一步:页面布局 <div class="col-sm-12 select-table table-striped" styl ...
- Linux性能优化实战学习笔记:第八讲
一.环境准备 1.在第6节的基础上安装dstat wget http://mirror.centos.org/centos/7/os/x86_64/Packages/dstat-0.7.2-12.el ...
- Npcap环境配置(Winpcap后继者) pcap的一种
Npcap是基于Winpcap和Libpcap的,Winpcap已多年无人维护,其官网也推荐Windows XP之后的用户转移到Npcap上.Npcap基于WINPCAP,Winpcap基于libpc ...
- 这篇文章主要讲解C#中的泛型,泛型在C#中有很重要的地位,尤其是在搭建项目框架的时候。
一.什么是泛型 泛型是C#2.0推出的新语法,不是语法糖,而是2.0由框架升级提供的功能. 我们在编程程序时,经常会遇到功能非常相似的模块,只是它们处理的数据不一样.但我们没有办法,只能分别写多个方法 ...
- 单调队列优化DP(超详细!!!)
一.概念 1.单调队列定义: 其实单调队列就是一种队列内的元素有单调性(单调递增或者单调递减)的队列,答案(也就是最优解)就存在队首,而队尾则是最后进队的元素.因为其单调性所以经常会被用来维护区间最值 ...
- 第09组 Beta冲刺(3/5)
队名:观光队 链接 组长博客 作业博客 组员实践情况 王耀鑫 过去两天完成了哪些任务 文字/口头描述 学习 展示GitHub当日代码/文档签入记录 接下来的计划 完成短租车,页面美化 还剩下哪些任务 ...