07-Go语言中map数据结构用法

map函数的原理

map是key-value结构的数据类型,类似于其他语言中的hash table,dict等

key必须是可hash的值,是一个确定的值(key的值不能设置了之后又发生了改变)

map存储的时候 hash(key) --> 固定的值 --> 把value放到对应的位置保存

map[key] : hash(key) --> 得到值 --> 取对应的value

map定义

GO语言中map的定义语法如下:

map[KeyType]ValueType

其中,

  • KeyType:表示键的类型。
  • ValueType:表示键对应的值的类型。

map类型的变量默认初始值为nil,需要使用make()函数初始化分配内存。语法为:

make(map[KeyType]ValueType,[cap])

其中cap表示map的容量,该参数虽然不是必须的,但是我们应该在初始化map的时候为其指定一个合适的容量。

map初始化

map初始化的方法有字面量初始化,make()函数初始化。

字面量初始化:

//字面量初始化
func f18() {
	var m map[string]int

	fmt.Println(m == nil) // true。map未初始化,值为nil

	m1 := map[string]string{
		"username": "王磊",
		"password": "1234", //花括号换行此处必须加逗号
	}
	fmt.Printf("%#v\n", m1) //
}

//运行结果:
true
map[string]string{"password":"1234", "username":"王磊"}

make()函数初始化:

//make函数初始化
func f19() {
	m2 := make(map[string]int) //只要初始化就可以赋值
	fmt.Println(m2 == nil)     //false,因为map已经初始化

	m2["wanglei"] = 120 //设置值
	fmt.Println(m2)

	weight := m2["wanglei"] //取值
	fmt.Println(weight)

}

//运行结果:
false
map[wanglei:120]
120
判断某个键是否存在

GO语言中有个判断map中键是否存在的特殊写法,格式如下:

value,ok := map[key]

举个例子:

//判断key是否存在
func f20() {
	m3 := make(map[string]int)

	m3["wanglei"] = 120
	m3["jack"] = 200
	// v,ok取值;OK是一个变量名,只不过大家约定俗成在这里用ok
	// OK=true表示map有这个key,ok=false表示map没这个key
	//如果没这个key,v等于对应类型的零值
	v, ok := m3["wanglei"]
	fmt.Println(v, ok) // 120 true

	v1, ok := m3["name"]
	fmt.Println(v1, ok) //0 false

	_, ok = m3["mike"]
	fmt.Println(ok) //false

}

//运行结果:
120 true
0 false
false
遍历
// map的遍历(map是无序的)
func f21() {
	m4 := map[string]int{
		"wanglei": 120,
		"小和尚":     200,
		"shahe":   234,
	}

	//遍历键和值
	for k, v := range m4 {
		fmt.Println(k, v)
	}

	//只遍历键
	for k1 := range m4 {
		fmt.Println(k1)
	}

	//只遍历值
	for _, v1 := range m4 {
		fmt.Println(v1)
	}
}

//运行结果:
wanglei 120
小和尚 200
shahe 234
wanglei
小和尚
shahe
120
200
234
从map中删除键值对

使用delete()内建函数从map中删除一组键值对,delete()函数的格式如下:

delte(map,key)

其中,

  • map:表示要删除键值对的map
  • key:表示要删除的键值对的键
// 从map中删除键值对
func f22() {
	m5 := make(map[string]int)
	m5["猪八戒"] = 200
	m5["孙悟空"] = 100
	m5["唐僧"] = 150

	delete(m5, "猪八戒")
	for k, v := range m5 {
		fmt.Printf("键为:%v 值为:%v\n", k, v)
	}

}

//运行结果:
键为:孙悟空 值为:100
键为:唐僧 值为:150
map+slice 组成复杂一点的数据类型
元素为map类型的切片
//元素为map类型的切片
func f23() {
	mapSlice := make([]map[string]string, 3) //定义了一个元素为map类型的,len=cap=3的切片
	fmt.Println(mapSlice)
	for index, value := range mapSlice {
		fmt.Printf("index:%d value:%v\n", index, value) // 得到的value都为map[]
	}
	fmt.Println("----------------after init----------------")
	//对切片的元素进行初始化
	mapSlice[0] = make(map[string]string)
	mapSlice[0]["name"] = "小王子"
	mapSlice[0]["password"] = "123456"
	mapSlice[0]["address"] = "沙河"
	fmt.Println(mapSlice)
	for index, value := range mapSlice {
		fmt.Printf("index:%d value:%v\n", index, value)
	}
	//继续可以按照对mapSlice[1],mapSlice[2]的元素初始化...
}

//运行结果:
[map[] map[] map[]]
index:0 value:map[]
index:1 value:map[]
index:2 value:map[]
----------------after init----------------
[map[address:沙河 name:小王子 password:123456] map[] map[]]
index:0 value:map[address:沙河 name:小王子 password:123456]
index:1 value:map[]
index:2 value:map[]
值为切片类型的map
//值为切片类型的map
func f24() {
	sliceMap := make(map[string][]string)
	fmt.Println(sliceMap)
	fmt.Println("-----------------after int-----------------")
	key := "中国"
	value, ok := sliceMap[key]
	if !ok {
		value = make([]string, 0, 2)
	}
	value = append(value, "北京", "上海")
	sliceMap[key] = value //map赋值
	fmt.Println(sliceMap)
}

//运行结果:
map[]
-----------------after int-----------------
map[中国:[北京 上海]]

练习

1、写一个程序,统计一个字符串中每个单词出现的次数。比如:”how do you do”中how=1 do=2 you=1。

//写一个程序,统计一个字符串中每个单词出现的次数。比如:"how do you do"中how=1 do=2 you=1
func f25() {
	/*
		1、先把字符串每个单词统计出来
		2、统计每个单词的数量
	*/

	str := "how do you do"
	slice := strings.Split(str, " ")
	fmt.Println(slice) //[how do you do]

	//定义一个map
	map1 := make(map[string]int)
	for _, value := range slice {
		_, ok := map1[value]
		if !ok { //	如果key不存在,则给这个key的value赋值1
			map1[value] = 1
		} else { //如果key存在,则在之前基础上+1
			map1[value] += 1
		}
	}
	fmt.Println(map1)

}

//运行结果:
[how do you do]
map[do:2 how:1 you:1]

2、观察下面代码,写出最终打印结果

// 下面代码打印结果
func f26() {

	type Map map[string][]int
	m := make(Map)
	s := []int{1, 2}
	s = append(s, 3)
	fmt.Printf("%+v\n", s) // [1 2 3]
	fmt.Printf("切片s的内存地址是:%p s: %v\n", s, s)

	m["q1mi"] = s
	fmt.Printf("m的内存地址是:%p m: %v\n", m, m)

	s = append(s[:1], s[2:]...)//等价于s[1]=3

	fmt.Printf("新切片s的内存地址是:%p s: %v\n", s, s) // 和之前的切片s的内存地址一样,因为底层操作的是同一个数组 [1 3]
	fmt.Printf("%+v\n", m["q1mi"])            //map[q1mi:[1 3 3] ?
}

//运行结果
[1 2 3]
切片s的内存地址是:0xc0000b4000 s: [1 2 3]
m的内存地址是:0xc000098180 m: map[q1mi:[1 2 3]]
新切片s的内存地址是:0xc0000b4000 s: [1 3]
[1 3 3]

你可能感兴趣的:(Golang,golang,运维开发,后端)