内容简介:• 引⽤类型。但⾃⾝是结构体,值拷⻉传递。• 属性 len 表⽰可⽤元素数量,读写操作不能超过该限制。• 属性 cap 表⽰最⼤扩张容量,不能超出数组限制。
切片slice:切片是对数组的抽象。切片在内存中占24个字节
runtime.h struct Slice{ // must not move anything byte* array; // actual data uintgo len; // number of elements uintgo cap; // allocated number of elements };
切片包含长度、容量、以及一个指向首元素的指针
• 引⽤类型。但⾃⾝是结构体,值拷⻉传递。
• 属性 len 表⽰可⽤元素数量,读写操作不能超过该限制。
• 属性 cap 表⽰最⼤扩张容量,不能超出数组限制。
• 如果 slice == nil,那么 len、 cap 结果都等于 0。
• 作为变长数组的替代方案,可以关联底层数组的局部或全部
•可以直接创建或从底层数组获取生成
• 使用len()获取元素个数,cap()获取容量
• 一般使用make()创建
•如果多个slice指向相同底层数组,其中一个值的改变会影响全部
•在通过下标访问元素时下标不能超过len大小,如同数组的下标不能超出len范围一样。
make([]T, len, cap)
其中cap可以省略,则和len的值相同
len表示存放的元素个数,cap表示容量
1、初始化的几种方式
//第一种方式创建切片 var slice []int fmt.Println(len(slice)) //0 //第二种方式 sl1 := []int{0, 1, 2, 3, 8: 100} // 通过初始化表达式构造,可使⽤索引号。 fmt.Println(sl1, len(sl1), cap(sl1)) //[0 1 2 3 0 0 0 0 100] 9 9 sl2 := make([]int, 10) // 使⽤ make 创建,省略 cap,相当于 cap = len。 fmt.Println(sl2) //[0 0 0 0 0 0 0 0 0 0] //第三种方式 num := []int{10, 20, 30, 40, 50} fmt.Println(num) //[10 20 30 40 50]
2、append
向 slice 尾部添加数据,返回新的 slice 对象
切片可以通过内置函数append(slice []Type,elems …Type)追加元素,elems可以是一排type类型的数据,也可以是slice,因为追加的一个一个的元素,因此如果将一个slice追加到另一个slice中需要带上”…”,这样才能表示是将slice中的元素依次追加到另一个slice中。append追加元素超出实际容量会执行扩容,会扩展为slice原先容量的2倍
(1)//将一个slice追加到另一个slice中需要带上”…”,这样表示是将slice中的元素依次追加到另一个slice中
例:
veggies := []string{"potatoes", "tomatoes", "brinjal"} fruits := []string{"oranges", "apples"} food := append(veggies, fruits...) //veggies+fruits fmt.Println("food:", food)
(2)切片元素删除,可以使用append来实现
s = append(s[:i], s[i+1:]…)
首先s[:i]相当于slice截取,也就是说s[:i]本身就是一个slice。然后s[i+1:]…相当于变长参数。使用append的特性(向 slice 尾部添加数据,返回新的 slice 对象)来实现删除的功能。可以单个也可以删除多个。
例:
//删除scile中元素,删除下标为2的元素 test := []int{10, 20, 30, 40, 50, 100} test = append(test[:2], test[3:]...) fmt.Println(test) //[10 20 40 50 100]
3、copy
函数 copy 在两个 slice 间复制数据,复制⻓度以 len ⼩的为准。两个 slice 可指向同⼀底层数组,允许元素区间重叠。
例:
//copy countries := []string{"USA", "Singapore", "Germany", "India", "Australia"} neededCountries := countries[:len(countries)-2] countriesCpy := make([]string, len(neededCountries)) copy(countriesCpy, neededCountries) fmt.Println(countriesCpy) fmt.Println(len(countriesCpy), cap(countriesCpy)) data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} s := data[8:] s2 := data[:5] copy(s2, s) // dst:s2, src:s fmt.Println(s2) //[8 9 2 3 4] fmt.Println(data) //[8 9 2 3 4 5 6 7 8 9]
应及时将所需数据 copy 到较⼩的 slice,以便释放内存。
下面是整个例子
package main import ( "fmt" "unsafe" ) func main() { //第一种方式创建切片 var slice []int fmt.Println(len(slice)) //0 //第二种方式 sl1 := []int{0, 1, 2, 3, 8: 100} // 通过初始化表达式构造,可使⽤索引号。 fmt.Println(sl1, len(sl1), cap(sl1)) //[0 1 2 3 0 0 0 0 100] 9 9 sl2 := make([]int, 10) // 使⽤ make 创建,省略 cap,相当于 cap = len。 fmt.Println(sl2) //[0 0 0 0 0 0 0 0 0 0] //第三种方式 num := []int{10, 20, 30, 40, 50} fmt.Println(num) //[10 20 30 40 50] fmt.Printf("type is %T\tsize is %d\n", sl2, unsafe.Sizeof(sl2)) var b []int b = num[1:4] //左闭右开从num下标1到3 var b1 []int b1 = num[:] //num的全部 fmt.Println(b) fmt.Println(b1) //切片为数组的引用 darr := [...]int{57, 89, 90, 82, 100, 78, 67, 69, 59} dslice := darr[2:5] fmt.Println("array before", darr) for i := range dslice { dslice[i]++ } fmt.Println("array after", darr) //切片指向数组,容量cap会从strartIndex取到数组结束,长度是指定截取长度 fruitarray := [...]string{"apple", "orange", "grape", "mango", "water melon", "pine apple", "chikoo"} fruitslice := fruitarray[0:3] //长度2容量6 fmt.Printf("length of slice %d capacity %d", len(fruitslice), cap(fruitslice)) //append追加元素超出实际容量会执行扩容,会扩展为原先容量的2倍 slice1 := make([]int, 5, 10) fmt.Println(slice1) slice3 := append(slice1, 1, 2, 3, 4, 5) fmt.Println(slice3) //执行append会会返回一个新的数值可以用原切片接收也可以使用别的 var slice4 []int //空的切片初始为nil fmt.Println(slice4) if slice4 == nil { slice4 = append(slice4, 1, 2, 3, 4) fmt.Println(slice4) } //将一个slice追加到另一个slice中需要带上"…",这样表示是将slice中的元素依次追加到另一个slice中 veggies := []string{"potatoes", "tomatoes", "brinjal"} fruits := []string{"oranges", "apples"} food := append(veggies, fruits...) //veggies+fruits fmt.Println("food:", food) //二维切片,每一行元素的个数可以不一致 pls := [][]string{ {"C", "C++"}, {"JavaScript"}, {"Go", "Rust"}, } fmt.Println(len(pls), cap(pls)) //长度为3容量为3 for _, v1 := range pls { for _, v2 := range v1 { fmt.Printf("%s ", v2) } fmt.Printf("\n") } //copy countries := []string{"USA", "Singapore", "Germany", "India", "Australia"} neededCountries := countries[:len(countries)-2] countriesCpy := make([]string, len(neededCountries)) copy(countriesCpy, neededCountries) fmt.Println(countriesCpy) fmt.Println(len(countriesCpy), cap(countriesCpy)) data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} s := data[8:] s2 := data[:5] copy(s2, s) // dst:s2, src:s fmt.Println(s2) //[8 9 2 3 4] fmt.Println(data) //[8 9 2 3 4 5 6 7 8 9] //删除scile中元素,删除下标为2的元素 test := []int{10, 20, 30, 40, 50, 100} test = append(test[:2], test[3:]...) fmt.Println(test) //[10 20 40 50 100] }
以上所述就是小编给大家介绍的《Golang学习笔记之切片(slice)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Go 学习笔记(11):切片
- Golang 学习笔记二 数组、切片
- 切片 - Go 语言学习笔记
- golang学习笔记10:数组切片Slice
- Go语言学习笔记05--切片slice与字典map
- Go语言快速入门笔记(2)--值类型和引用类型,silce切片,map映射
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
疯狂Java讲义
李刚 / 电子工业出版社 / 2008-10 / 99.00元
《疯狂Java讲义》2000年至今,Java语言一直是应用最广的开发语言,并拥有最广泛的开发人群。如今,Java已经不再简单地是一门语言,它更像一个完整的体系,一个系统的开发平台。更甚至,它被延伸成一种开源精神。 《疯狂Java讲义》深入介绍了Java编程的相关方面,全书内容覆盖了Java的基本语法结构、Java的面向对象特征、Java集合框架体系、Java泛型、异常处理、Java GUI编......一起来看看 《疯狂Java讲义》 这本书的介绍吧!