Golang 切片

Golang 切片

定义

  1. 切片是数组的一个引用, 因此切片是引用类型, 在进行传递时, 遵守引用传递的机制

    func main() {
       //定义一个切片
       arr := [...]int{1, 2, 3, 4}
       //表示截取arr的[1,3)
       sArr := arr[1:3]
       fmt.Println(sArr)  //2,3
       sArr[0] =10
       fmt.Println(sArr)//10,3 用于是引用变量, 所以修改切片也会修改数组
       fmt.Println(arr)// 1,10,3,4
    }
    
  2. 切片的使用和数组类似, 遍历切片, 访问切片的元素和求切片长度len(slice)都一样

  3. 切片的长度是可以变化的, 因此切片是一个可以动态变化的数组

  4. 切片的定义基本语法:

    var identifier [] type

    func main() {
    	//定义一个切片
    	arr := [...]int{1, 2, 3, 4}
    	//表示截取arr的[1,3)
    	sArr := arr[1:3]
    	fmt.Println(sArr) //2 ,3
    }
    
  5. slice底层, 其实是一个结构体

    type slice struct{
    	p *[len]int
    	len int //切片长度
    	cap int //切片容量
    }
    

创建切片

使用切片时, 必须初始化

	var slice []int //slice未初始化 [], len == 0
	fmt.Println(slice)
	slice[0] = 20// len == 0 panic
	fmt.Println(slice)

方式一: 截取数组

func main() {
	arr := [4]int{1,2,3,4}
	slice1 := arr[0:2] // 截取[0,2)
	fmt.Println(slice1)
}

slice的指针指向左闭区间, slice修改值, 外部数组值同时修改

方式二: make

  • 指定切片的长度和容量, capacity >= length
  • 如果没有给切片的元素赋值, 就会使用默认值
  • 通过make创建的切片对应的数组是由make 底层维护, 对外不可见, 只能通过slice访问各个元素
func main() {
	//slice2 := make([]int, 3)len 3,缺省cap, 默认cap == len
	slice2 := make([]int, 3,10)//len 3 , cap 10, cap >= len
	fmt.Printf("slice2 %v, capacity %v, len %v",slice2,cap(slice2),len(slice2))
}

没有一个变量指向数组, 只能通过slice访问内存空间

方式三: slice[]{}

类似于make(type, len), 默认cap == len

func main() {
    var str []string = []string{}//等价 var str = []string{}
	strings := []string{"tom","Jack","Lucy"}//区别于数组arr := [3]int{1,2,3}
	fmt.Printf("strings %v, len %v,cap %v",strings,len(strings),cap(strings))
}

遍历切片

方式一: 普通for循环

func main() {
	slice := []string{"a","b","c","d"}
	for i := 0; i < len(slice); i++ {
		fmt.Printf("%s",slice[i])
	}
}

方式二: for - range

func main() {
	slice := []string{1: `world`, 0: `hello`}
	for idx, val := range slice {
		fmt.Printf("%d, %s 
", idx, val)
	}
}

注意事项

  1. arr[start : end]简写

    func main() {
    	arr := [4]int{1, 2, 3, 4}
    	slice := arr[:2] //如果从0开始,等价于 arr[0:2]
    	fmt.Println(slice)
    	slice = arr[1:] //如果到len(arr),等价于 arr[1:len(arr)]
    	fmt.Println(slice)
    	slice = arr[:]//如果从0到len(arr),等价于 arr[0:len(arr)]
    	fmt.Println(slice)
    }
    
  2. cap是一个内置函数, 用于统计切片的容量, 即最大可以存放多少个元素

  3. 切片定义完后, 还不能使用, 因为本身是一个空的, 需要让其引用到一个数组, 或者make一个空间供切片使用

  4. 切片可以继续切片, 用于是引用类型, slice2改变slice1和数组也会改变

    func main() {
    	arr := [4]int{1, 2, 3, 4}
    	slice1 :=arr[:]
    	fmt.Println(slice1)
    	//切片可以继续切片
    	slice2 := slice1[:3]
    	fmt.Println(slice2)
        -------------------------
        arr := [3]int{100,200,300}
    	slice1 := arr[:]
    	slice2 := slice1[:]
    	fmt.Println(slice1,slice2)
    	slice2[0] = 400
    	fmt.Println(slice1,slice2)
    }
    
  5. append内置函数, 可以对切片进行动态追加, 通过make返回

    func main() {
    	slice := []int{100,200,300}
    	fmt.Println(slice)
    	//append返回一个新的切片
    	slice = append(slice, 400, 500)
    	fmt.Println(slice)
        -----------------------
        slice1 := []int{100, 200, 300}
    	slice2 := []int{400, 500}
    	//追加一个切片到slice
    	slice1 = append(slice1, slice2...)
    	fmt.Println(slice1)
    }
    
  6. 切片使用copy内置函数完成拷贝, 如果slice2的长度小于slice1同样会执行

    func main() {
    	slice1 := []int{100,200,300}
    	slice2 := make([]int,5)
    	fmt.Println(slice2)
    	//将slice1拷贝到slice2
    	copy(slice2,slice1 )
    	fmt.Println(slice2)
    }
    
原文地址:https://www.cnblogs.com/kikochz/p/13473194.html