Go学习第二章内建容器
2.1.数组
数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,数组元素可以通过索引来读取(或修改),定义方法:
package main import ( "fmt" ) func main() { //var定义数组可不赋初值 var arr1 [5]int //[0 0 0 0 0] //冒号定义需指定初值 arr2 := [3]int{1,3,5} //[1 3 5] //...表示任意个数 arr3 := [...]int{2,4,6,8,10} //[2 4 6 8 10] fmt.Println(arr1,arr2,arr3) //数组的遍历可获取下标和值,不想取可用_符号 for i,v := range arr3{ fmt.Println(i,v) } }
数组是值类型,传递到函数中会复制一份而不会修改原值并且[10]int和[20]int不是同一类型:
package main import ( "fmt" ) func printArray(arr [5]int){ arr[1] = 100 } func main() { arr2 := [3]int{1,3,5} //arr3 := [...]int{2,4,6,8,10} printArray(arr2) //报错 }
2.2.切片
切片是数组的抽象,数组的长度不可改变,与数组相比切片(动态数组)的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大,定义方式:
package main import "fmt" func main() { arr := []int{0,1,2,3,4,5,6,7} // 声明一个未指定大小的数组来定义切片 fmt.Println(arr[:6]) arr2 := make([]int,16) // 通过make函数,后面是长度 fmt.Printf("len(s3)=%d,cap(s3)=%d\n",len(s3),cap(s3)) //len(s3)=16,cap(s3)=16 arr3 := make([]int,16,32) // 也可以指定容量 fmt.Printf("len(s4)=%d,cap(s4)=%d\n",len(s4),cap(s4)) //16,32 }
切片的扩展可以向后,不可以向前扩展:
package main import "fmt" func main() { arr := [...]int{0,1,2,3,4,5,6,7} s1 := arr[2:4] s2 := s1[3:5] fmt.Println("arr = ",arr) //arr = [0 1 2 3 4 5 6 7] fmt.Printf("s1=%v,len(s1)=%d,cap(s1)=%d\n",s1,len(s1),cap(s1)) //s1=[2 3],len(s1)=2,cap(s1)=6 fmt.Printf("s2=%v,len(s2)=%d,cap(s2)=%d\n",s2,len(s2),cap(s2)) //s2=[5 6],len(s2)=2,cap(s2)=3 fmt.Println(s1[3:6]) //[5 6 7] }
切片增加元素时,如果超出了容量,系统会重新分配更大的底层数组,由于是值传递,增加元素时必须接收返回值:
package main import "fmt" func main() { arr := [...]int{0,1,2,3,4,5,6,7} s1 := arr[2:6] //[2 3 4 5] s2 := s1[3:5] //[5 6] s3 := append(s2,10) s4 := append(s3,11) fmt.Println(s1,s2,s3,s4) //[5 6 10] [5 6 10 11] //因为s2的容量是[5,6,7],append把7替换成10,s4超出了容量 fmt.Println(arr) //[0 1 2 3 4 5 6 10] }
2.3.Map
map是一种无序的键值对的集合,Map 最重要的是通过key来快速检索数据,定义方式:
package main import "fmt" func main() { // map关键字定义 括号是key类型外面的string是值类型 m1 := map[string]string{ "name": "derek", "course": "go", "city": "guangdong", } fmt.Println(m1) //map[city:guangdong course:go name:derek] //通过make函数定义 m2 := make(map[string]int) fmt.Println(m2) //map[] }
map的使用:
package main import "fmt" func main() { m1 := map[string]string{ "name": "derek", "course": "go", "city": "guangdong", } m1["sale"] = "boby" //插入 sale, ok := m1["sale"] //检查是否存在元素 存在ok为True 否则sale的值为空 fmt.Println(sale,ok) // boby,true delete(m1,"sale") //删除 fmt.Println(m1) for k,v := range m1{ fmt.Println(k,v) //遍历 } }
2.4.new和make
由于引用数据类型(slice,map,channel等)和指针必须在创建内存后才可使用,所以把一个无初始数据的引用数据类型赋值给变量需要使用make函数分配空间:
var userInfo = make(map[string]string) userInfo["userName"] = "zhangsan" fmt.Println(userInfo) var array = make([]int, 4, 4) // 切片slice array[0] = 1 fmt.Println(array)
new用于类型的内存分配,返回的是指向类型的指针,make用于slice.map.channel的初始化,返回的是引用类型的本身:
// 指针变量初始化错误方法 会报错 var a *int *a = 100 fmt.Println(a) // 使用new关键字创建指针 aPoint := new(int) bPoint := new(bool) fmt.Printf("%T \n", aPoint) // 下面四个值*int *bool 0 false fmt.Printf("%T \n", bPoint) fmt.Println(*aPoint) fmt.Println(*bPoint)