1.Slice(切片)代表變長的序列,序列中每個元素都有相同的類型,一個slice類型一般寫作[]T,其中T代表slice中元素的類型;slice的語法和數組很像,只是沒有固定長度而已,slice的底層確實引用一個數組對象 2.內置的len和cap函數分別返回slice的長度和容量 3.s[i:j] ...
1.Slice(切片)代表變長的序列,序列中每個元素都有相同的類型,一個slice類型一般寫作[]T,其中T代表slice中元素的類型;slice的語法和數組很像,只是沒有固定長度而已,slice的底層確實引用一個數組對象
2.內置的len和cap函數分別返回slice的長度和容量
3.s[i:j] , 從第i個元素開始到第j-1個元素的子序列,s[:]切片操作則是引用整個數組
4.slice值包含指向第一個slice元素的指針,因此向函數傳遞slice將允許在函數內部修改底層數組的元素
5.將slice元素迴圈向左旋轉n個元素的方法是三次調用reverse反轉函數,第一次是反轉開頭的n個元素,然後是反轉剩下的元素,最後是反轉整個slice的元素。
6.slice之間不能比較,因此我們不能使用==操作符來判斷兩個slice是否含有全部相等元素,slice唯一合法的比較操作是和nil比較
7.可以用[]int(nil)類型轉換表達式來生成一個對應類型slice的nil值
8.測試一個slice是否是空的,使用len(s) == 0來判斷
9.make函數創建一個指定元素類型、長度和容量的slice , make([]T, len)
10.內置的append函數用於向slice追加元素
11.[]rune("Hello, 世界") 字元串轉rune類型的slice
12.我們並不知道append調用是否導致了記憶體的重新分配,因此我們也不能確認新的slice和原始的slice是否引用的是相同的底層數組空間,通常是將append返回的結果直接賦值給輸入的slice變數
13.函數參數中的最後的“...”省略號表示接收變長的參數為slice,func appendInt(x []int, y ...int) []int {}
14.報錯invalid indirect of s[j] (type int) ,使用數組指針的時候(*s)[0]
15.Slice記憶體技巧,
練習 4.3: 重寫reverse函數,使用數組指針代替slice。
練習 4.4: 編寫一個rotate函數,通過一次迴圈完成旋轉。
練習 4.5: 寫一個函數在原地完成消除[]string中相鄰重覆的字元串的操作。
練習 4.6: 編寫一個函數,原地將一個UTF-8編碼的[]byte類型的slice中相鄰的空格(參考unicode.IsSpace)替換成一個空格返回
練習 4.7: 修改reverse函數用於原地反轉UTF-8編碼的[]byte。是否可以不用分配額外的記憶體?
package main import( "fmt" "unicode" ) func main(){ testArr := [5]int{0,1,2,3,4} //reverse(&testArr) fmt.Println(testArr) a:=rotate(testArr[:],2) fmt.Println(a) b:=[]string{"tao","taoshihan","shi","shi","han"} emptyString(b) d:=[]byte("abc bcd wer sdsd taoshihan de") e:=emptyString2(d) fmt.Println(string(e)) f:=[]byte("abc bcd wer sdsd taoshihan de") reverse1(f) fmt.Println(string(f)) } /* 練習 4.3: 重寫reverse函數,使用數組指針代替slice。 */ func reverse(s *[5]int){ i,j := 0,len(*s)-1; for i<j{ (*s)[i],(*s)[j]=(*s)[j],(*s)[i] i+=1 j-=1 } } /* 練習 4.4: 編寫一個rotate函數,通過一次迴圈完成旋轉。 */ func rotate(s []int,r int)[]int{ lens := len(s) //創建一個空的指定長度的slice res :=make([]int, lens) for i:=0 ;i<lens;i++{ index := i+r if index>=lens{ index=index-lens } res[i] = s[index] } return res } /* 練習 4.5:寫一個函數在原地完成消除[]string中相鄰重覆的字元串的操作。 */ func emptyString(s []string)[]string{ i:=0 index:=0 num := len(s) for _,v :=range s{ index =i+1 if index>=num{ break } if v != s[index]{ s[i]=v i++ } } fmt.Println(s[:i]) return s[:i] } /* 練習 4.6: 編寫一個函數,原地將一個UTF-8編碼的[]byte類型的slice中相鄰的空格(參考unicode.IsSpace)替換成一個空格返回 */ func emptyString2(s []byte)[]byte{ index:=0 num := len(s) for i:=0;i<num;i++{ index =i+1 num = len(s) if index>=num{ break } if unicode.IsSpace(rune(s[i])) && unicode.IsSpace(rune(s[index])){ //結合remove函數 copy(s[i:],s[index:]) s=s[:len(s)-1] i-- } } return s } /* 練習 4.7: 修改reverse函數用於原地反轉UTF-8編碼的[]byte。是否可以不用分配額外的記憶體? */ func reverse1(s []byte) { for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { s[i], s[j] = s[j], s[i] } }