Golang 之 Slice切片

1. 创建切片

//定义一个空切片,注意[]中没有指定长度,如果指定长度,就代表是数组了
var slice []int
fmt.Println(slice) //[]

// 申明slice时,建议使用var方式申明,不建议使用大括号的方式,var方式申明在slice不被append的情况下避免了内存分配
GOOD: var t []string
BAD:  t := []string{}

// 在一个nil的slice中添加元素是没问题的,但对一个nil map做同样的事将会生成一个运行时的panic
var s []int
s = append(s,1) // 正确

//创建一个长度和容量为5的切片
slice1 := []int{1, 2, 3, 4, 5}
fmt.Println(slice1)                   //[1 2 3 4 5]
fmt.Println(len(slice1), cap(slice1)) //5 5
 
//创建一个长度和容量为6的切片
slice2 := []int{5: 10}
fmt.Println(slice2)                   //[0 0 0 0 0 10]
fmt.Println(len(slice2), cap(slice2)) //6 6
 
//使用make创建切片
//make(type,len,cap),未指定cap是,cap和len相等
slice3 := make([]int, 5, 10)
fmt.Println(slice3, len(slice3), cap(slice3)) //[0 0 0 0 0] 5 10
slice4 := make([]int, 6)
fmt.Println(slice4, len(slice4), cap(slice4)) //[0 0 0 0 0 0] 6 6
 
//利用数组创建切片
//[strat:end]左闭右开,start省略时,默认为0;end省略时默认为数组或者切片长度
arr := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
slice5 := arr[3:]
fmt.Println(slice5)  //[3 4 5 6 7 8 9]
 
slice6 := arr[:7]
fmt.Println(slice6)  //[0 1 2 3 4 5 6]
 
slice7 := arr[4:8]
fmt.Println(slice7)  //[4 5 6 7]
 
slice8 := arr[:]
fmt.Println(slice8)  //[0 1 2 3 4 5 6 7 8 9]

2. len()函数

        通过len函数求切片长度,判断是否为空。

3. append()函数

// 使用append函数后,返回的是一个slice类型,不是数组类型
// 不能对数组调用append函数,即append函数的第一个参数必须是slice。
slice := []int{1, 2, 3, 4, 5}
fmt.Println(slice) //[1 2 3 4 5]
 
//追加元素
slice = append(slice, 6)
fmt.Println(slice) //[1 2 3 4 5 6]
 
//追加切片
s1 := []int{99, 100}
//注意下面的...表示解构,即,将切片的内容展开后填充到该位置
slice = append(slice, s1...)
fmt.Println(slice)

4. copy()函数

// copy(destination,resource),复制之后,dest的长度并不会改变,即使复制给他的切片长度远大于它。
// 不能使用copy进行数组的复制操作,即,copy的两个参数都必须是slice。

//长的slice复制到短的slice
s1 := []int{1, 2, 3, 4, 5}
s2 := []int{10, 20, 30, 40}
copy(s2, s1)
fmt.Println(s2) //[1 2 3 4]
 
//短的slice复制到长的slice
s3 := []int{2, 3, 4}
s4 := []int{9, 8, 7, 6, 5}
copy(s4, s3)
fmt.Println(s4) //[2 3 4 6 5]
 
//相同长度的slice进行复制
s5 := []int{1, 2, 3}
s6 := []int{4, 5, 6}
copy(s6, s5)
fmt.Println(s6) //[1 2 3]

5. 作为函数参数

package main
 
import "fmt"
 
//参数是数组类型
func Double(arr [5]int) {
    for i := 0; i < 5; i++ {
        arr[i] *= 2
    }
}
 
//参数是slice类型
func Triple(slice []int) {
    for i := 0; i < len(slice); i++ {
        slice[i] *= 3
    }
}
func main() {
    arr := [5]int{1, 2, 3, 4, 5}
    Double(arr)
    fmt.Println(arr)  //[1 2 3 4 5]
 
    //数组转换为切片
    slice := arr[:]
    Triple(slice)
    fmt.Println(arr)  //[3 6 9 12 15]
}

6. reslice操作

package main

import "fmt"

func main() {
	slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}
	fmt.Println(slice, len(slice), cap(slice)) //[0 1 2 3 4 5 6 7 8] 9 9
	newSlice := slice[6:8]
	fmt.Println(newSlice, len(newSlice), cap(newSlice)) //[6 7] 2 3
	
	//向newSlice中添加一个元素,注意此时,刚好len(newSlice) == cap(newSlice)
	newSlice = append(newSlice, 111)
	fmt.Println(slice, len(slice), cap(slice))          //[0 1 2 3 4 5 6 7 111] 9 9
	fmt.Println(newSlice, len(newSlice), cap(newSlice)) //[6 7 111] 3 3

	//再向newSlice中添加一个元素,注意此时,
	//刚好向后扩展newSlice时,已经超过了原slice的cap,超过的部分,不会反映到原slice
	newSlice = append(newSlice, 222)
	fmt.Println(slice, len(slice), cap(slice))   //[0 1 2 3 4 5 6 7 111] 9 9
	fmt.Println(newSlice, len(newSlice), cap(newSlice))  //[6 7 111 222] 4 6
}



综上所述:当我们调用append向一个新的slice添加元素时:

  如果新的slice在append之后,新slice的cap没有改变(即新slice的len仍小于新slice的cap),那么,至少在cap改变之前,append的行为结果都会反映到原slice

  如果新的slice在append之后,新slice的cap改变了,那么,新的slice就拥有了自己的底层数组,所以,append的行为结果不会反映到原slice,但是cap没有改变之前,仍会反映到原slice,只是在cap改变之后,才不会反映到slice

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值