go 切片(创建、nil切片、空切片、切片拷贝)

一、什么是切片

1.切片就是一个“动态”数组,即切片的长度是可以伸缩的。其数据结构是一个结构体,包含三个字段,指向数组的指针、长度、容量。

type slice struct {
    array unsafe.Pointer  //一个指向数组的指针
    len   int
    cap   int
}

2.切片的指针指向某个数组,所以它是引用类型。

go 切片(创建、nil切片、空切片、切片拷贝)_第1张图片

3.代码验证切片是引用类型

package main

import "fmt"

//传入切片
func change(s []string) { 
	s[1] = "c++"
}

func main() {
	lang := []string{"golang","java","php","js"}
	fmt.Println(lang[1])  //java
	change(lang)
	fmt.Println(lang[1])  //c++
}

二、切片创建

1.申明并创建(分两步:1-声明  2-make初始化)

var s1 []int           //申明
s1 = make([]int , 2)   //分配内存

2.直接make()创建

var s []int = make([]int , 6)

3. 推导make创建

s := make([]int , 6)

4.从数组中截取

arr := [8]int{1,2,3,4,5,6,7,8}
s := arr[1:5]

三、nil切片和空切片

1.nil切片:声明为切片,但是没有分配内存。切片的指针是nil

注意:只有声明的切片才会产生nil切片,通过推导或数组截取的切片都是指针有指向的。

var s []int

2.空切片:切片指针指向了一个数组内存地址,但是数组是空的。 空切片有两种方式产生,如下:

s1 := []int{}   //1.空切片,没有任何元素

s2 := make( []int, 0)  //2.make 切片,没有任何元素

3.nil切片和空切片的本质区别就是: nil切片没有分配内存,空切片是有分配内存但底层指向的是一个空数组 

 四、用数组 和 切片  初始化切片

1.初始化

arr := [5]int{1, 2, 3, 4, 5} //数组

s1 := arr[:]                 //数组初始化切片

s2 := s1[:]                  //切片s1初始化切片s2

2.截取操作符 [ startIndex : endIndex ]

注意截取中的startIndex、endIndex 指的是数组或切片的下标位置,startIndex是截取时开始的位置,endIndex是结束的位置而不包含结束位置的元素

go 切片(创建、nil切片、空切片、切片拷贝)_第2张图片

 2.数组截取初始化切片实例

全局变量:
var arr = [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} //这是一个数组
var slice0 []int = arr[start:end] 
var slice1 []int = arr[:end]        
var slice2 []int = arr[start:]        
var slice3 []int = arr[:] 
var slice4 = arr[:len(arr)-1]      //去掉切片的最后一个元素
局部变量:
arr2 := [...]int{9, 8, 7, 6, 5, 4, 3, 2, 1, 0}  //这是一个数组
slice5 := arr[start:end]
slice6 := arr[:end]        
slice7 := arr[start:]     
slice8 := arr[:]  
slice9 := arr[:len(arr)-1] //去掉切片的最后一个元素

五、操作切片的函数  append()   copy()

1.切片尾部追加元素 append()

注意:如下合并其他切片时,需要   ... 来展开切片

data := [...]int{0, 1, 2, 3, 4, 10: 0} //数组
s  := data[:]
s2 := data[1:5]
s = append(s,100)         //1.追加1个元素
s = append(s,200,300,400) //2.追加多个元素
s = append(s,s2...)       //3.合并其他切片
                     

2.切片的拷贝:切片分为 1-浅拷贝  2-深拷贝(copy())

2.1 浅拷贝 :源切片和目的切片共享同一底层数组空间

  slice1 := make([]int, 5, 5)
  slice2 := slice1
  slice1[1] = 1
  fmt.Println(slice1) //[0 1 0 0 0]
  fmt.Println(slice2) //[0 1 0 0 0]

2.2深拷贝:源切片和目的切片各自都有彼此独立的底层数组空间, 

注意:copy(s1,s2),是将源切片的内容拷贝到目的切片中,即将s2元素拷贝到s1中,如果s1长度3,s2的长度5,那么复制到s2则将前三个元素覆盖到s1的三个元素上。

    slice1 := make([]int, 5, 5)
	slice1[0] = 9
	fmt.Println(slice1)
	slice2 := make([]int, 4, 4)
	slice3 := make([]int, 5, 5)
	fmt.Println(slice2)
	fmt.Println(slice3)
	//拷贝
	fmt.Println(copy(slice2, slice1)) //4
	fmt.Println(copy(slice3, slice1)) //5
	//独立修改
	slice2[1] = 2
	slice3[1] = 3
	fmt.Println(slice1) //[9 0 0 0 0 0]
	fmt.Println(slice2) //[9 2 0 0]
	fmt.Println(slice3) //[9 3 0 0 0]

结果:

[9 0 0 0 0]
[0 0 0 0]
[0 0 0 0 0]
4
5
[9 0 0 0 0]
[9 2 0 0]
[9 3 0 0 0]

你可能感兴趣的:(go,切片,go)