Go语言map、list及关键字make&new
map和列表是两种容器,make&new是创建以及初始化结构的
一、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,值是hahah
二、map
map是一种数据结构,采用键值对的存储格式,是一种无序的数据结构,引用类型的容器,在其他语言中也叫字典,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()
- 通过声明初始化list
var 变量名 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