1、切片创建
切片(slice)解决了数组长度不能扩展,以及基本类型数组传递时产生副本的问题。
常用创建方式:
1 2 3 4
   | var s1 []int				 s2 := []byte {'a','b','c'} fmt.Println(s1)				 fmt.Print(s2)				
 
  | 
 
使用make函数创建:
1 2 3
   | slice1 := make([]int,5)		 slice2 := make([]int,5,7)	 slice3 := []int{1,2,3,4,5}	
 
  | 
 
从数组创建:slice 可以从一个数组再次声明。slice 通过 array[i:j] 来获取,其中 i 是数组的开始位置,j 是结束位置,但不包含 array[j],它的长度是 j-i:
1 2 3 4 5 6 7 8 9 10
   |  var arr = [10]byte {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
 
  var a, b []byte
 
  a = arr[2:5]		
  b = arr[3:5]
 
  | 
 
注意:声明数组时,方括号内写明了数组的长度或使用…自动计算长度,而声明 slice 时,方括号内没有任何字符。  
从切片创建:
1 2
   | oldSlice := []int{1,2,3} newSlice := oldSlice[:6]	
 
  | 
 
注意:如果选择的旧切片长度超出了旧切片的 cap() 值(切片存储长度),则不合法。  
2、切片常见操作
2.1、切片常见内置函数
切片常用内置函数:
1 2 3 4
   | len()			                返回切片长度 cap()			                返回切片底层数组容量 append()		                对切片追加元素 func copy(dst, src []Type) int  将src中数据拷贝到dst中,返回拷贝的元素个数
 
  | 
 
切片空间与元素个数:
1 2 3 4
   | slice1 := make([]int, 5, 10) fmt.Println(len(slice1))			 fmt.Println(cap(slice1))			 fmt.Println(slice1)					
 
  | 
 
切片操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
   |  slice1 = append(slice1,1,2) fmt.Println(slice1)						
 
  sliceTemp := make([]int,3) slice1 = append(slice1,sliceTemp...) fmt.Println(slice1)						
 
  s1 := []int{1,3,6,9} s2 := make([]int, 10)	 num := copy(s2, s1)
  fmt.Println(s1)			 fmt.Println(s2)			 fmt.Println(num)		
 
  s1 := []int{1,3,6,9} index := 2					 s1 = append(s1[:index], s1[index+1:]...) fmt.Println(s1)				
 
  s1 := []int{1,2,3,4,5} s2 := []int{6,7,8} copy(s1,s2) 				 copy(s2,s1)	 				
 
  | 
 
注意:没有…会编译错误,默认第二个参数后是元素值,传入切片需要展开。如果追加的长度超过当前已分配的存储空间,切片会自动分配更大的内存。  
2.2、切片的一些简便操作
- slice 的默认开始位置是0,
ar[:n] 等价于 ar[0:n] 
- slice 的第二个序列默认是数组的长度,
ar[n:] 等价于 ar[n:len(ar)] 
- 如果从一个数组里面直接获取 slice,可以这样 
ar[:],因为默认第一个序列是0,第二个是数组的长度,即等价于 ar[0:len(ar)] 
- 切片的遍历可以使用 for 循环,也可以使用 range 函数
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
   |  var array = [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
  var aSlice, bSlice []byte
 
  aSlice = array[:3]   aSlice = array[5:]   aSlice = array[:]   
 
  aSlice = array[3:7]   bSlice = aSlice[1:3]  bSlice = aSlice[:3]   bSlice = aSlice[0:5]  bSlice = aSlice[:]    ```  
 
  ## 2.3、切片的截取
  *   `s[n]`:切片s中索引为位置为n的项 *   `s[:]`:从切片s的索引位置0到`len(s)-1`所获得的切片 *   `s[low:]`:从切片s的索引位置low到`len(s)-1`所获得的切片 *   `s[:high]`:从切片s的索引位置0到high所获得的切片 *   `s[low:high]`:从切片s的索引位置low到high所获得的切片 *   `s[low:high:max]`:从low到high的切片,且容量`cap=max-low`
 
  ## 2.4、字符串转切片  
  ```go str := "hello,世界" a := []byte(str)		 b := []rune(str)		
 
  | 
 
3、切片存储结构
与数组相比,切片多了一个存储能力值的概念,即元素个数与分配空间可以是两个不同的值,其结构如下所示:
1 2 3 4 5
   | type slice struct { 	arrary = unsafe.Pointer		 	len int						 	cap int						 }
 
  | 
 
所以切片通过内部的指针和相关属性引用数组片段,实现了变长方案,Slice 并不是真正意义上的动态数组。  
合理设置存储能力,可以大幅提升性能,比如知道最多元素个数为50,那么提前设置为50,而不是先设为30,可以明显减少重新分配内存的操作。  
4、切片作为函数参数
1 2 3 4 5 6 7 8 9 10 11 12 13
   | func test(s []int) { 	fmt.Printf("test---%p\n", s)  	s = append(s, 1, 2, 3, 4, 5) 	fmt.Printf("test---%p\n", s)  	fmt.Println("test---", s)     }
  func main() { 	s1 := make([]int, 3) 	test(s1) 	fmt.Printf("main---%p\n", s1)  	fmt.Println("main---", s1)     }
 
  |