map和列表是两种容器,make&new是创建以及初始化结构的
make和new关键字是用来创建以及初始化结构的。
make只用于chan、map以及切片的内存创建,返回的还是这三个引用类型本身;
因为这三种类型是引用类型,所以必须得初始化。对于引用类型的变量,我们不光要声明它,还要为它分配内容空间。
make和new关键字都分配内存。
而new返回的是指向类型的指针。
func main() { //make创建切片,已被初始化 slice := make([] int, 3) slice[0]=1 slice[1]=2 fmt.Printf("slice的类型是%T\n",slice) //make创建map,已被初始化 maps:=make(map[int] int) maps[0]=2 //已被初始化的map可以存放数据 fmt.Printf("maps的类型是%T\n",maps) //返回一个指针 l:=new(string) var n string n="hahah" l=&n fmt.Printf("l的类型是%T,地址是%p,值是%v",l,&l,*l) } slice的类型是[]int maps的类型是map[int]int l的类型是*string,地址是0xc000006030,值是hahahmap是一种数据结构,采用键值对的存储格式,是一种无序的数据结构,引用类型的容器,在其他语言中也叫字典,hash等。
键:值,键和值分别有自己的类型
声明及初始化
//创建map的三种方式 var map1 map[int]string//只做声明,未被初始化,不能存放数据 var map2 map[int]string=map[int]string{1:"hello",2:"yes",4:"my",3:"王二狗",9:"隔壁老王"} //key和value都是string map3:=make(map[string]string)增删改查
map通过键来访问数据,增加数据,修改数据,使用delete()来删除数据。
//访问和改变都通过key改变 map3["one"]="Hi" map3["two"]="boy" //删除元素[map,key] delete(map2,3) delete(map2,1)遍历
遍历使用for和range关键字,其中返回的是键和值
for k,v:=range map{ }具体实例见下
package main import "fmt" func main() { //创建map的三种方式 var map1 map[int]string//只做声明,未被初始化,不能存放数据 var map2 map[int]string=map[int]string{1:"hello",2:"yes",4:"my",3:"王二狗",9:"隔壁老王"} //key和value都是string map3:=make(map[string]string) fmt.Printf("map1的类型是%T,值是%v\n",map1,map1) fmt.Printf("map2的类型是%T,值是%v\n",map2,map2) fmt.Printf("map3的类型是%T,值是%v\n",map3,map3) fmt.Println("----------------------") map1=map2 fmt.Println("map1[1] : "+map1[1]) //访问和改变都通过key改变 map3["one"]="Hi" map3["two"]="boy" fmt.Println("map3的值: ",map3) fmt.Println("----------------------") //遍历键值 for k,v:=range map2{ fmt.Printf("key为%v,值为%v\n",k,v) } fmt.Println("----------------------") //删除元素[map,key] delete(map2,3) delete(map2,1) fmt.Println("----------------------") fmt.Println("遍历map2") for k,v:=range map2{ fmt.Printf("key为%v,值为%v\n",k,v) } fmt.Println("..............................") fmt.Println("遍历map1") //引用类型,原数据也被修改了 for k,v:=range map1{ fmt.Printf("key为%v,值为%v\n",k,v) } } map1的类型是map[int]string,值是map[] map2的类型是map[int]string,值是map[1:hello 2:yes 3:王二狗 4:my 9:隔壁老王] map3的类型是map[string]string,值是map[] ---------------------- map1[1] : hello map3的值: map[one:Hi two:boy] ---------------------- key为9,值为隔壁老王 key为1,值为hello key为2,值为yes key为4,值为my key为3,值为王二狗 ---------------------- ---------------------- 遍历map2 key为9,值为隔壁老王 key为2,值为yes key为4,值为my .............................. 遍历map1 key为2,值为yes key为4,值为my key为9,值为隔壁老王列表不是go内置的数据结构,来自"container/list"包下,底层基于双链表。
列表与切片和 map 不同的是,列表并没有具体元素类型的限制。因此,列表的元素可以是任意类型。这既带来遍历,也会引来一些问题。给一个列表放入了非期望类型的值,在取出值后,将 interface{} 转换为期望类型时将会发生宕机。
声明及初始化
通过 container/list 包的 New 方法初始化 list变量名 := list.New()
通过声明初始化listvar 变量名 list.List
列表操作涉及到方法,可以查看文档。
package main import ( "container/list" "fmt" ) func main() { //初始化 var l =list.New() var h list.List //从后加入元素 h.PushBack("hahhahhhh") l.PushBack("Hello") l.PushFront("你好") l.PushFront(111) //取值 fmt.Println(l.Front().Value) fmt.Println(l.Back().Value) //获取长度 fmt.Println(l.Len()) p:=Animal{"Jack",19} //加入结构体 l.PushBack(p) fmt.Println("最后一位元素的值是",l.Back().Value) //返回元素的指针 ptr:=l.PushBack("NO") fmt.Println(ptr) //插入到指定元素之前 l.InsertBefore("nice",ptr) //遍历 for i:=l.Front();i!=nil;i=i.Next(){ fmt.Println(i.Value) } //删除元素,通过指针标记 l.Remove(ptr) fmt.Println("...........................") //再遍历 for i:=l.Back();i!=nil;i=i.Prev(){ fmt.Println(i.Value) } } type Animal struct { name string age int } 111 Hello 3 最后一位元素的值是 {Jack 19} &{0xc00005c330 0xc00005c450 0xc00005c330 NO} 111 你好 Hello {Jack 19} nice NO ........................... nice {Jack 19} Hello 你好 111