go 语言之map

map

map 的声明

map 是key -value 数据结构,又称为字段或者关联数组。类似其他编程语言的集合;在编程中是经常使用到的

基本语法

var map 变量名, map[key type] valuetype

golang 中的map的key 可以是很多种类型,比如bool,数字,string,指针,channel,还可以是包含前面几个类型的接口,结构体,数组通常为int、string

注意 slice ,map 还有function不可以,是因为这几个没法用==来判断

valuetype 可以是什么类型

valuetype 的类型和key 基本一样,通常为数字(整型,浮点数)

声明map

   var a map[string]string
   var b map[string]int
   var c map[int]string
   var d map[string]map[string]string

  注意声明不会分配内存的,初始化需要make,分配内存后才能赋值使用

 初始化

package main

import "fmt"

//"fmt"
func main(){
   var a map[string]string//声明
	a = make(map[string]string,10)//初始化
	a["a1"]= "宋江"
	a["a2"]= "吴用"
	a["a3"]= "吴用"
	a["a1"]= "武松"
	a["a4"]= "林冲"//v可以重复;无序的key-v结构go
	fmt.Println(a)
}
//执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom01\main.go
// map[a1:武松 a2:吴用 a3:吴用 a4:林冲]

1)map 在使用前一定要make

2) map 的key 是不能重复,如果重复key,则覆盖上一个value值

3)map的value 的值是可以重复的

4)map 的key-value 是无序的

make 内置函数

func make(Type, size IntegerType) Type
内建函数make分配并初始化一个类型为切片、映射、或通道的对象。其第一个实参为类型,而非值。make的返回类型与其参数相同,而非指向它的指针。其具体结果取决于具体的类型:

切片:size指定了其长度。该切片的容量等于其长度。切片支持第二个整数实参可用来指定不同的容量;
     它必须不小于其长度,因此 make([]int, 0, 10) 会分配一个长度为0,容量为10的切片。
映射:初始分配的创建取决于size,但产生的映射长度为0。size可以省略,这种情况下就会分配一个
     小的起始大小。
通道:通道的缓存根据指定的缓存容量初始化。若 size为零或被省略,该信道即为无缓存的。

  map 的使用方式

 

package main
import (
	"fmt"
)
func main(){
	//方式1
	//声明
	var cities1 map[string]string
	//使用make 初始化
	cities1= make(map[string]string)
	cities1["a"]= "golang"
	//方式2声明并初始化
	var cities2 = make(map[string]string)
	cities2["q"]="你好"
	//方式3 声明初始化并赋值(make没有明确写,但底层给make了)
	var cities3 map[string]string= map[string]string{"node1":"晨曦"}
	cities3["node2"]= "上海"
	fmt.Println("方式1",cities1)
	fmt.Println("方式2",cities2)
	fmt.Println("方式3",cities3)
	cities4 := map[string]string{
		"悟空":"金箍棒",
		"八戒":"九齿钉耙",
		"沙和尚":"降魔杖",
		"哪吒":"火尖枪",
	}
	fmt.Println("方式4",cities4)
}
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom02\main.go
// 方式1 map[a:golang]
// 方式2 map[q:你好]
// 方式3 map[node1:晨曦 node2:上海]
// 方式4 map[八戒:九齿钉耙 哪吒:火尖枪 悟空:金箍棒 沙和尚:降魔杖]

  示例1

package main
import (
	"fmt"
)
func main(){
	//方式1
	//声明
	var cities1 map[string]string
	//使用make 初始化
	cities1= make(map[string]string)
	cities1["a"]= "golang"
	//方式2声明并初始化
	var cities2 = make(map[string]string)
	cities2["q"]="你好"
	//方式3 声明初始化并赋值(make没有明确写,但底层给make了)
	var cities3 map[string]string= map[string]string{"node1":"晨曦"}
	cities3["node2"]= "上海"
	fmt.Println("方式1",cities1)
	fmt.Println("方式2",cities2)
	fmt.Println("方式3",cities3)
	cities4 := map[string]string{
		"悟空":"金箍棒",
		"八戒":"九齿钉耙",
		"沙和尚":"降魔杖",
		"哪吒":"火尖枪",
	}
	fmt.Println("方式4",cities4)
	cities5 := make(map[string]map[string]string)
	//cities5= make(map[string]map[string]string)
	cities5["学生1"]= make(map[string]string)//这句话不能少
	cities5["学生2"]= make(map[string]string)
	cities5["学生3"]= make(map[string]string)
	cities5["学生1"]["名字"]= "tom"
	cities5["学生1"]["性别"]= "男"
	cities5["学生1"]["地址"]= "胡同"
	cities5["学生2"]["名字"]= "丽娜"
	cities5["学生2"]["性别"]= "女"
	cities5["学生2"]["地址"]= "天通苑"
	cities5["学生3"]["名字"]= "杰克"
	cities5["学生3"]["性别"]= "男"
	cities5["学生3"]["地址"]= "青年汇"
	fmt.Println(cities5["学生3"])
}
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom02\main.go
// 方式1 map[a:golang]
// 方式2 map[q:你好]
// 方式3 map[node1:晨曦 node2:上海]
// 方式4 map[八戒:九齿钉耙 哪吒:火尖枪 悟空:金箍棒 沙和尚:降魔杖]
// map[名字:杰克 地址:青年汇 性别:男]

  map 的增删改成操作

package main
import (
	"fmt"
)
func main(){
	a := make(map[string]string)
	a["a1"]= "阿库"
	a["a2"]= "小米"
	a["a3"]= "小鹿"
	a["a4"]= "小鹏"
	fmt.Println("修改前打印",a)
	//修改a[a2的值]
	a["a2"]="小白"
	fmt.Println("修改后打印",a["a2"])
	fmt.Println("修改打印",a)
	//增加一个
	a["w1"]= "奶茶"
	fmt.Println("增加新值打印",a)
	//删除一个值
	delete(a,"a3")

	fmt.Println("删除后打印",a)

}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom03\main.go
// 修改前打印 map[a1:阿库 a2:小米 a3:小鹿 a4:小鹏]
// 修改后打印 小白
// 修改打印 map[a1:阿库 a2:小白 a3:小鹿 a4:小鹏]
// 增加新值打印 map[a1:阿库 a2:小白 a3:小鹿 a4:小鹏 w1:奶茶]
// 删除后打印 map[a1:阿库 a2:小白 a4:小鹏 w1:奶茶]

  delete 删除操作

func delete(m map[Type]Type1, key Type)
内建函数delete按照指定的键将元素从映射中删除。若m为nil或无此元素,delete不进行操作。

  细节说明

1)如果我们要删除map 的所有key,没有一个专门的方法一次性删除,可以遍历删除

package main
import (
	"fmt"

)
func main(){
	a := make(map[string]string)
	a["a1"]= "阿库"
	a["a2"]= "小米"
	a["a3"]= "小鹿"
	a["a4"]= "小鹏"
	fmt.Println("修改前打印",a)
	//修改a[a2的值]
	a["a2"]="小白"
	fmt.Println("修改后打印",a["a2"])
	fmt.Println("修改打印",a)
	//增加一个
	a["w1"]= "奶茶"
	fmt.Println("增加新值打印",a)
	//删除一个值
	delete(a,"a3")

	fmt.Println("删除后打印",a)
	// 遍历整个map集合
	fmt.Println("变量整个map")
	for i,v := range a{
		fmt.Println(i,v)
	}


	//遍历所以value
	//遍历整个map 集合的key 与value
	fmt.Println("遍历整个map 集合的key 与value")
	for _,v := range a{
		fmt.Println(v)
	}

	// 希望删除所有key;遍历逐一删除;遍历键时可以使用下面方法
	fmt.Println("遍历删除整个集合")
	for k := range a{
		delete(a,k)
	}
	fmt.Println("清空后打印",a)
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom03\main.go
// 修改前打印 map[a1:阿库 a2:小米 a3:小鹿 a4:小鹏]
// 修改后打印 小白
// 修改打印 map[a1:阿库 a2:小白 a3:小鹿 a4:小鹏]
// 增加新值打印 map[a1:阿库 a2:小白 a3:小鹿 a4:小鹏 w1:奶茶]
// 删除后打印 map[a1:阿库 a2:小白 a4:小鹏 w1:奶茶]
// 变量整个map
// a1 阿库
// a2 小白
// a4 小鹏
// w1 奶茶
// 遍历整个map 集合的key 与value
// 小鹏
// 奶茶
// 阿库
// 小白
// 遍历删除整个集合
// 清空后打印 map[]

  

2)或者map= make(...),make一个新的,让原来的成为垃圾,被gc回收

 

     

package main
import (
	"fmt"

)
func main(){
	a := make(map[string]string)
	a["a1"]= "阿库"
	a["a2"]= "小米"
	a["a3"]= "小鹿"
	a["a4"]= "小鹏"
	fmt.Println("修改前打印",a)
	//修改a[a2的值]
	a["a2"]="小白"
	fmt.Println("修改后打印",a["a2"])
	fmt.Println("修改打印",a)
	//增加一个
	a["w1"]= "奶茶"
	fmt.Println("增加新值打印",a)
	//删除一个值
	delete(a,"a3")

	fmt.Println("删除后打印",a)
	fmt.Println("删除整个集合",a)
	a = map[string]string{}
	fmt.Println("清空后打印",a)
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom03\main.go
// 修改前打印 map[a1:阿库 a2:小米 a3:小鹿 a4:小鹏]
// 修改后打印 小白
// 修改打印 map[a1:阿库 a2:小白 a3:小鹿 a4:小鹏]
// 增加新值打印 map[a1:阿库 a2:小白 a3:小鹿 a4:小鹏 w1:奶茶]
// 删除后打印 map[a1:阿库 a2:小白 a4:小鹏 w1:奶茶]
// 删除整个集合 map[a1:阿库 a2:小白 a4:小鹏 w1:奶茶]
// 清空后打印 map[]

  查找

package main
import (
	"fmt"

)
func main(){
	a := make(map[string]string)
	a["a1"]= "阿库"
	a["a2"]= "小米"
	a["a3"]= "小鹿"
	a["a4"]= "小鹏"

	// 查找
	val,ok := a["a1"]
	if ok{
		fmt.Println("有这个a1 key;值为",val)
	}else {
		fmt.Println("没有有这个a1 key;值为")
		
	}

}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom03\main.go
// 有这个a1 key;值为 阿库

  遍历

package main
import (
	"fmt"

)
func main(){
	a := make(map[string]string)
	a["a1"]= "阿库"
	a["a2"]= "小米"
	a["a3"]= "小鹿"
	a["a4"]= "小鹏"
	//遍历k
	fmt.Println("遍历k")
	for k:= range a{
		fmt.Println(k)
	}
	//遍历整个几个
	fmt.Println("遍历整个集合")
	for v,k := range a{
		fmt.Println(v,k)
	}

}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom04\main.go
// 遍历k
// a1
// a2
// a3
// a4
// 遍历整个集合
// a1 阿库
// a2 小米
// a3 小鹿
// a4 小鹏

  示例2

package main
import (
	"fmt"

)
func main(){
	cities5 := make(map[string]map[string]string)
	//cities5= make(map[string]map[string]string)
	cities5["学生1"]= make(map[string]string)//这句话不能少
	cities5["学生2"]= make(map[string]string)
	cities5["学生3"]= make(map[string]string)
	cities5["学生1"]["名字"]= "tom"
	cities5["学生1"]["性别"]= "男"
	cities5["学生1"]["地址"]= "胡同"
	cities5["学生2"]["名字"]= "丽娜"
	cities5["学生2"]["性别"]= "女"
	cities5["学生2"]["地址"]= "天通苑"
	cities5["学生3"]["名字"]= "杰克"
	cities5["学生3"]["性别"]= "男"
	cities5["学生3"]["地址"]= "青年汇"
	for x := range cities5{
		for i,v := range cities5[x]{
			fmt.Printf("学生%v的%v是%v\n",x,i,v)
		}
	}

}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom04\main.go
// 学生学生1的名字是tom
// 学生学生1的性别是男
// 学生学生1的地址是胡同
// 学生学生2的名字是丽娜
// 学生学生2的性别是女
// 学生学生2的地址是天通苑
// 学生学生3的性别是男
// 学生学生3的地址是青年汇
// 学生学生3的名字是杰克

  统计长度

数组:v中元素的数量
数组指针:*v中元素的数量(v为nil时panic)
切片、映射:v中元素的数量;若v为nil,len(v)即为零
字符串:v中字节的数量
通道:通道缓存中队列(未读取)元素的数量;若v为 nil,len(v)即为零
package main
import (
	"fmt"

)
func main(){
	a := make(map[string]string)
	a["a1"]= "阿库"
	a["a2"]= "小米"
	a["a3"]= "小鹿"
	a["a4"]= "小鹏"

	fmt.Println("map a 的长度",len(a))


}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom04\main.go
// map a 的长度 4

  map切片

切片的基本数组如果是map 。称为slice of map,map切片,这样使用则map个数就可以动态变化了

package main
import (
	"fmt"
)
func main(){
	var mosters []map[string]string
	mosters = make([]map[string]string,2)//初始化切片
	if mosters[0]== nil{
		mosters[0]= make(map[string]string)
		mosters[0]["名字"]="牛魔王"
		mosters[0]["年龄"]="1600"	
	}
	if mosters[1]== nil{
		mosters[1]= make(map[string]string)
		mosters[1]["名字"]="牛魔王"
		mosters[1]["年龄"]="1600"	
	}
	a := map[string]string{
		"name": "黑熊怪",
		"age" : "1400",
	}
	mosters= append(mosters, a)
	fmt.Println(mosters)
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom05\main.go
// [map[名字:牛魔王 年龄:1600] map[名字:牛魔王 年龄:1600] map[age:1400 name:黑熊怪]]

  map的排序

1)golang中没有一个专门的方法针对map的key 进行排序

2)golang 中map 默认是无序的,注意也不是按照添加顺序存放的,每次遍历得到的输出可能不一样

3)golang 中map 的排序,是先将key 进行排序,然后根据key的值遍历

示例

package main

import (
	"fmt"
	"sort"
)
func main(){
	map1 :=make(map[int]int)
	map1[0]=0
	map1[1]=1
	map1[67]=9
	map1[5]=98
	fmt.Println(map1)
	//如何安装map的key顺序进行排序输出
	//1. 先将map的key 放到切片中
	//2.对切片进行排序
	//3遍历切片。按照k
	keys := []int{}
	for k := range map1{
		keys=append(keys,k)
	}
	fmt.Println(keys)
	fmt.Println("排序前打印map")
	for i,v := range map1{
		fmt.Printf("排序前map[%v]=%v ",i,v)
	}
	fmt.Println()

// 排序
    sort.Ints(keys)
	fmt.Println(keys)

	//排序打印map
	for _,v := range keys{
		fmt.Printf("排序后map[%v]=%v ",v,map1[v])
	}

}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom05\main.go
// map[0:0 1:1 5:98 67:9]
// [0 1 67 5]
// 排序前打印map
// 排序前map[67]=9 排序前map[5]=98 排序前map[0]=0 排序前map[1]=1
// [0 1 5 67]
// 排序后map[0]=0 排序后map[1]=1 排序后map[5]=98 排序后map[67]=9
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom06\main.go
// map[0:0 1:1 5:98 67:9]
// [5 0 1 67]
// 排序前打印map
// 排序前map[0]=0 排序前map[1]=1 排序前map[67]=9 排序前map[5]=98
// [0 1 5 67]
// 排序后map[0]=0 排序后map[1]=1 排序后map[5]=98 排序后map[67]=9
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom06\main.go
// map[0:0 1:1 5:98 67:9]
// [0 1 67 5]
// 排序前打印map
// 排序前map[1]=1 排序前map[67]=9 排序前map[5]=98 排序前map[0]=0
// [0 1 5 67]
// 排序后map[0]=0 排序后map[1]=1 排序后map[5]=98 排序后map[67]=9

  map使用细节

1)map 是引用数据类型,遵守引用类型传递的机制在一个函数接收map,修改后,会直接修改原来的map

package main

import "fmt"

func modify(map1 map[int]int){
	map1[10] =900
}
func main(){
	map1 := make(map[int]int)
	map1[10] = 20
	map1[29] = 89
	fmt.Println("map1=",map1)
	modify(map1)
	fmt.Println("修改后map=",map1)
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom05\main.go
// map1= map[10:20 29:89]
// 修改后map= map[10:900 29:89]

  

2)map 的容量达到后,在想map增加元素,会自动扩容,并不会panic ,也就是说map能动态的增长键值对(key-value)

package main

import "fmt"

func modify(map1 map[int]int){
	map1[10] =900
}
func main(){
	map1 := make(map[int]int,2)
	map1[10] = 20
	map1[29] = 89
	fmt.Println("map1=",map1)
	modify(map1)
	fmt.Println("修改后map=",map1)
	map1[43]= 98
	fmt.Println("增加一个键值对后map=",map1)
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom05\main.go
// map1= map[10:20 29:89]
// 修改后map= map[10:900 29:89]
// 修改后map= map[10:900 29:89 43:98]

  

3)map 的value也经常使用struct类型,更适合管理更复杂的数据结构(例如value 是一个map更好),比如value为student 结构体

package main

import "fmt"

func modify(map1 map[int]int){
	map1[10] =900
}
type sty  struct{
	name string
	age  int 
	add string
}
func main(){
	students := make(map[string]sty,10)
	//创建
	stu1 := sty{"tom", 29, "天通苑"}
	stu2 := sty{"lina", 29, "胡同"}
	stu3 := sty{"小杰", 29, "青年汇"}
	students["cx"] = stu1
	students["cw"] = stu2
	students["no2"] = stu3
	fmt.Println(students)
	
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom05\main.go
// map[cw:{lina 29 胡同} cx:{tom 29 天通苑} no2:{小杰 29 青年汇}]

  遍历

package main

import "fmt"

func modify(map1 map[int]int){
	map1[10] =900
}
type sty  struct{
	name string
	age  int 
	add string
}
func main(){
	students := make(map[string]sty,10)
	//创建
	stu1 := sty{"tom", 29, "天通苑"}
	stu2 := sty{"lina", 29, "胡同"}
	stu3 := sty{"小杰", 29, "青年汇"}
	students["cx"] = stu1
	students["cw"] = stu2
	students["no2"] = stu3
	fmt.Println(students)
	for i,v := range students{
		fmt.Printf("学生编号%v\n",i)
		fmt.Printf("学生名字%v\n",v.name)
		fmt.Printf("学生住址%v\n",v.add)
		fmt.Printf("学生年龄%v\n",v.age)
	}
	
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom05\main.go
// map[cw:{lina 29 胡同} cx:{tom 29 天通苑} no2:{小杰 29 青年汇}]
// 学生编号cx
// 学生名字tom
// 学生住址天通苑
// 学生年龄29
// 学生编号cw
// 学生名字lina
// 学生住址胡同
// 学生年龄29
// 学生编号no2
// 学生名字小杰
// 学生住址青年汇
// 学生年龄29

  练习

package main

import "fmt"

func modify(map1 map[int]int){
	map1[10] =900
}
type sty  struct{
	name string
	age  int 
	add string
}
func test(a map[string]map[string]string,name string){

	if a[name] !=nil { // 判断是map否存在某key
		//有用户
		a[name]["pws"] = "888888"
	} else {
		//fmt.Println("输入用户名")
		a[name] = make(map[string]string)
		a[name]["pwd"]= "88888"
		a[name]["昵称"]= "昵称"+name

	}
}
func main(){
	t := make(map[string]map[string]string)
	t["go"] = make(map[string]string)
	t["go"]["pwd"]="999999"
	t["go"]["昵称"]="Golang"
	test(t,"tom")
	test(t,"dagu")
	test(t,"go")
	fmt.Println(t)
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter08\deom05\main.go
// map[dagu:map[pwd:88888 昵称:昵称dagu] go:map[pwd:999999 pws:888888 昵称:Golang] tom:map[pwd:88888 昵称:昵称tom]]

  

 

posted @ 2026-03-15 20:10  烟雨楼台,行云流水  阅读(1)  评论(0)    收藏  举报