第二章 内建容器(数组,切片和容器)
数组
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(
"黑化肥挥发发灰会花飞灰化肥挥发发黑会飞花"))
}