第二章 內建容器(數組,切片和容器)
數組
var arr1 [ 5 ] int
arr2 := [ 3 ] int { 1 , 3 , 5 }
arr3 := [ ... ] int { 2 , 3 , 4 , 5 , 6 }
var grid[ 4 ] [ 5 ] int
func printArray ( arr [ 5 ] int ) {
for i := 0 ; i < len ( arr) ; i++ {
fmt. Println ( i, arr[ i] )
}
}
func printArray ( arr [ 5 ] int ) {
for i, v := range arr {
fmt. Println ( i, v)
}
}
數組是值類型(作爲函數參數是值傳遞)
[10]int 和 [20]int 是不同的類型
go語言中一般不直接使用數組
Slice 切片
1. Slice本身沒有數據,是對底層arry的一個view, 修改Slice的值會修改對應的arry的值
arr := [ ... ] int { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 }
slice1 = arr[ 2 : 6 ]
slice2 = arr[ 2 : ]
slice3 = arr[ : 6 ]
sliceAll = arr[ : ]
func updateSlice ( s [ ] int ) {
s[ 0 ] = 100
}
2. ReSlice
arr := [ ... ] int { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 }
s := arr[ 2 : 6 ]
s = s[ : 3 ]
s = s[ 1 : ]
s = s[ : ]
3. Slice的實現
ptr 指向Arry的某一個index, 作爲Slice的index = 0 的位置
len 爲Slice的長度, s[ index] 的index必須 >= 0 && < len , 否則會 out of range
cap 爲從ptr開始到Arry最後一個元素的長度
4. Slice的擴展
arr := [ ... ] int { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 }
s1 = arr[ 2 : 6 ]
s2 = s1[ 3 : 5 ]
fmt. Printf ( "s1=%v, len(s1)=%d, cap(s1)=%d\n" , s1, len ( s1) , cap ( s1) )
fmt. Printf ( "s2=%v, len(s2)=%d, cap(s2)=%d\n" , s2, len ( s2) , cap ( s2) )
Slice可以向後擴展,不可以向前擴展
s[i] 不可以超越 len(s), 向後擴展不可以超越底層數組的cap(s)
5. 向Slice添加元素
s3 := append ( s2, 10 )
s4 := append ( s3, 11 )
s5 := append ( s4, 12 )
fmt. Println ( "s3, s4, s5 =" , s3, s4, s5)
fmt. Println ( "arr =" , arr)
添加元素時如果超越cap,系統會重新分配更大的底層數組
由於值傳遞的關係,必須接收append的返回值
6. 創建Slice
var s [ ] int
s1 := [ ] int { 2 , 4 , 6 , 8 }
s2 := make ( [ ] int , 16 )
s3 := make ( [ ] int , 10 , 32 )
7. 拷貝Slice
copy ( s2, s1)
8. 刪除Slice中的元素
s2 = append ( s2[ : 3 ] , s2[ 4 : ] ... )
front := s2[ 0 ]
s2 = s2[ 1 : ]
tail := s2[ len ( s2) - 1 ]
s2 = s2[ : len ( s2) - 1 ]
在移除元素的時候,len ( slice) 始終會減少, 但是cap ( slice) 只有在移除首個元素的時候纔會減少
因爲在移除首個元素的時候,Slice的ptr發生了改變,向後移動了一個元素, cap 的長度自然也要減少
Map 容器
1. Map結構
map [ K] V
map [ K1 ( map [ K2] V)
2. 創建Map
m := map [ string ] string {
"name" : "ccmouse" ,
"course" : "golang" ,
"site" : "imooc" ,
"quality" : "notbad" ,
}
m2 := make ( map [ string ] int )
3. 遍歷map, 不保證遍歷順序
for k, v := range m {
fmt. Println ( k, v)
}
4. 獲取數據m[key],如果輸入的key不存在,返回的是ZeroValue( “map[]” )
courseName := m[ "course" ]
5. 用value, ok:=m[key]來判斷是否存在key
if causeName, ok := m[ "cause" ] ; ok {
fmt. Println ( causeName)
} else {
fmt. Println ( "key 'cause' does not exist" )
}
6. 刪除數據
delete ( m, "name" )
7.使用len獲取元素個數
len ( m)
8. map的key
map 使用哈希表,必須可以比較相等
除了slice,map ,function的內建類型都可以作爲key
Struct類型不包含上述字段,也可以作爲key
rune
rune相當於go的char
使用 utf8.RuneCountInString 獲取字符數量
使用 len 獲得字節長度
使用 []byte 獲得字節
練習
尋找最長不含有重複字符串的子串
lastOccurred[x]不存在,或者 < start ->無需操作
lastOccurred[x] >= start -> 更新start
更新lastOccurred[x],更新maxLength
func lengthOfNonRepeatingSubStr ( s string ) int {
lastOccurred := make ( map [ rune ] int )
start := 0
maxLength := 0
for i, ch := range [ ] rune ( s) {
if lastI, ok := lastOccurred[ ch] ; ok && lastI >= start {
start = lastI + 1
}
if i- start+ 1 > maxLength {
maxLength = i - start + 1
}
lastOccurred[ ch] = i
}
return maxLength
}
func main ( ) {
fmt. Println (
lengthOfNonRepeatingSubStr ( "abcabcbb" ) )
fmt. Println (
lengthOfNonRepeatingSubStr ( "bbbbb" ) )
fmt. Println (
lengthOfNonRepeatingSubStr ( "pwwkew" ) )
fmt. Println (
lengthOfNonRepeatingSubStr ( "" ) )
fmt. Println (
lengthOfNonRepeatingSubStr ( "b" ) )
fmt. Println (
lengthOfNonRepeatingSubStr ( "abcdef" ) )
fmt. Println (
lengthOfNonRepeatingSubStr ( "這裏是慕課網" ) )
fmt. Println (
lengthOfNonRepeatingSubStr ( "一二三二一" ) )
fmt. Println (
lengthOfNonRepeatingSubStr (
"黑化肥揮發發灰會花飛灰化肥揮發發黑會飛花" ) )
}