数组
定义数组
var arr1 [5]int
arr2 := [3]int{1,3,5}
arr3 := [...]int{2,4,6,8} //使用编译器来推断数组中的元素[...],如果不写...就是切片
fmt.Println(arr1, arr2, arr3)
var grid [4][5]int
fmt.Println(grid)
遍历数组
for i := 0; i < len(arr3); i++{
fmt.Println(arr3[i])
}
for i, v := range arr3{
fmt.Println(i,v)
}
数组是值类型,在传递的时候会拷贝数组。
[10]int和[20]int是不同的类型。
func printArray(arr [5]int) {
arr[0] = 100 //这里修改,对于外部传入的数组是不会改变的
for i, v := range arr {
fmt.Println(i, v)
}
}
切片
在go语言中一般不直接使用数组,也不使用指向数组的指针,一般都使用数组的切片。slice是array的一个view,也可以进行reslice。
func updateSlice(s []int){
s[0] = 100 //因为传参是slice,因此修改是影响传入的数组
}
arr := [...]int{0,1,2,3,4,5,6,7}
updateSlice(arr[:])
//可以进行reslice
s2 := arr[:]
s2 = s2[:5]
s2 = s2[2:]
slice可以向后扩展,不能向前扩展。
s[i]不能超过len(s),向后扩展不能超过cap(s)。
slice的添加操作
添加元素时如果超过了cap,系统会重新分配更大的底层数组
由于在append的时候,slice底层实现中的len和cap都有可能改变,因此必须接受append的返回值
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))
s3 := append(s2,10)
s4 := append(s3,11) //往s3中再append就会超过s3的cap,因次会重新分配一个更大的底层数组
s5 := append(s4,12)
// s4 and s5 no longer view arr
fmt.Println("s3, s4, s5 = ", s3, s4, s5)
fmt.Println("arr = ",arr)
/*
s1=[2 3 4 5], len(s1)=4, cap(s1)=6
s2=[5 6], len(s2)=2, cap(s2)=3
s3, s4, s5 = [5 6 10] [5 6 10 11] [5 6 10 11 12]
arr = [0 1 2 3 4 5 6 10]
*/
slice的创建
var s []int // zero value for slice is nil
for i := 0; i < 5; i++{
printSlice(s)
s = append(s,i)
}
s1 := []int{2,3,4,8}
printSlice(s1)
s2 := make([]int,16) //创建长度为16的slice
printSlice(s2)
s3 := make([]int,10,32)
printSlice(s3)
copy(s2, s1) //[2 3 4 8 0 0 0 0 0 0 0 0 0 0 0 0] len=16, cap=16
printSlice(s2)
//删除s2中的8,无现成的函数
s2 = append(s2[:3], s2[4:]...) //[2 3 4 0 0 0 0 0 0 0 0 0 0 0 0] len=15, cap=16
printSlice(s2)
//删除头
front := s2[0]
s2 = s2[1:]
//删除尾
tail := s2[len(s2)-1]
s2 = s2[:len(s2)-1]
fmt.Println(front,tail)
Map
//map的创建
m := map[string]string{
"name": "ccmouse",
"course": "golang",
"site": "imooc",
}
fmt.Println(m)
m1 := make(map[string]int) // m1 == empty map
fmt.Println(m1)
var m2 map[string]int // m2 == nil
fmt.Println(m2)
//map的遍历
for k,v := range m {
fmt.Println(k,v)
}
//取的map中的value
courseName,ok := m["course"] //使用这个ok 来判断是否存在这个key
fmt.Println(courseName,ok)
if causeName,ok := m["cause"]; ok{//使用[]取不存在的的key,会返回一个空的value
fmt.Println(causeName,ok)
}else{
fmt.Println("Key does not exit")
}
//删除map中的key
delete(m, "name")
//map添加key
m["cause"] = "aaa"
for k,v := range m {
fmt.Println(k,v)
}
字符串的操作
rune相当于go中的char,是int32类型,支持中文。而C/C++中的char是int8,只支持英文的ASCII码。len获得是字符串的字节数目。
go语言中所有的字符串都是utf-8编码的,但是单个字符是unicode编码的。
s := "Yes我爱慕课网!"// 字符串默认是utf-8编码 每个中文是3字节,英文是1字节
fmt.Printf("%d", len(s)) //len获得字节的长度
fmt.Println(s)
for _, b := range []byte(s){
fmt.Printf("%X ", b)
}
fmt.Println()
for i, ch := range s{
//range s会将utf-8进行解码,然后编码成unicode放入ch中
fmt.Printf("(%d %X)", i,ch)
}
fmt.Println()
for i, ch := range s{
//range s会将utf-8进行解码,然后编码成unicode放入ch中
fmt.Printf("(%d %c)", i,ch)
}
fmt.Println()
fmt.Println("Rune count: ",utf8.RuneCountInString(s)) //获得字符数量
//拿到每一个字符
bytes := []byte(s)
for len(bytes) > 0{
ch, size := utf8.DecodeRune(bytes)
bytes = bytes[size:]
fmt.Printf("%c ", ch)
}
fmt.Println()
//直接拿到每一个字符
//rune是4字节,是重新开了一个每个元素都是4字节的数组
for i, ch := range []rune(s){
fmt.Printf("(%d %c)", i,ch)
}
/*
19Yes我爱慕课网!
//utf-8编码
59 65 73 E6 88 91 E7 88 B1 E6 85 95 E8 AF BE E7 BD 91 21
//unicode编码
(0 59)(1 65)(2 73)(3 6211)(6 7231)(9 6155)(12 8BFE)(15 7F51)(18 21)
(0 Y)(1 e)(2 s)(3 我)(6 爱)(9 慕)(12 课)(15 网)(18 !)
Rune count: 9
Y e s 我 爱 慕 课 网 !
(0 Y)(1 e)(2 s)(3 我)(4 爱)(5 慕)(6 课)(7 网)(8 !)
*/