GO-map

1.Map的介绍

Go语言中的map(映射、字典)是一种内置的数据结构,它是一个无序的key-value对的集合,比如以身份证号作为唯一键来标识一个人的信息。Go语言中并没有提供一个set类型,但是map中的key也是不相同的,可以用map实现类似set的功能。

map格式为:

map[keyType]valueType

在一个map里所有的键都是唯一的,而且必须是支持==和!=操作符的类型,****切片、函数*以及包含切片的结构类型这些类型由于具有*引用****语义,****不能作为映射的键****,使用这些类型会造成编译错误:

dict := map[ []string ]int{}    //err, invalid map key type []string

map值可以是任意类型,没有限制。map里所有键的数据类型必须是相同的,值也必须如此,但键和值的数据类型可以不相同。

2.map的创建和初始化

//Map creation method one
	var m1 map[int]string
	if m1 == nil {
		fmt.Println("map is nil")	
	}
	// map creation method two
	m2 := map[int]string{}
	fmt.Println(len(m2))
	fmt.Println(m2)
	
	m2[7]="Fuck"
	fmt.Println(m2)

	//map creation method three
	m3 := make(map[int]string)
	fmt.Println(len(m3))
	fmt.Println(m3)
	m3[300]= "WDNMD"
	fmt.Println(m3)

	//map creation method four
	m4:= make(map[int]string,8)
	fmt.Println(len(m4))  //0
	fmt.Println(m4)
	m4[250]= "MDZZ"
	fmt.Println(m4)

创建m4的方法指定了map的初始创建容量。 与slice类似,后期在使用过程中,map可以自动扩容。只不过map更方便一些,不用借助类似append的函数,直接赋值即可。如,m1[17] = “Nami”。赋值过程中,key如果与已有map中key重复,会将原有map中key对应的value覆盖。

但是!对于map而言,可以使用len()函数,但map 不能使用cap()

初始化map

也可以直接指定初值,要保证key不重复。

// Initialization of map
	var m1 map[int]string = map[int]string{1:"MDZZ",2:"SHA"}
	fmt.Println(m1)

	// Initialization of map two :=
	m2 := map[int]string{1:"Love",2:"Hate"}
	fmt.Println(m2)

	//map assignment
	m3 := make(map[int]string,100)

	m3[1] ="aaa"
	m3[1] ="ddd"  //modify value
	m3[2] ="ccc"  //add value

	fmt.Println(m3)

3.遍历map 和判断map中key 是否存在

Map的迭代顺序是不确定的,并且不同的哈希函数实现可能导致不同的遍历顺序。在实践中,遍历的顺序是随机的,每一次遍历的顺序都不相同。这是故意的,每次都使用随机的遍历顺序可以强制要求程序不会依赖具体的哈希函数实现。

m4 := map[int]string{1:"Love",2:"Hate",3:"MDZZ",4:"SHA"}
	for k,v := range m4{
		fmt.Printf("%d ===== %s\n",k,v)
	}

	for k := range m4{
		fmt.Println(k,m4[k]) 
	}
}

有时候可能需要知道对应的元素是否真的是在map之中。可以使用下标语法判断某个key是否存在。map的下标语法将产生两个值,其中 第一个是value值 第二个是一个布尔值,用于报告元素是否真的存在

v,BOOL := m4[1]
	fmt.Println(v,BOOL) //Love true

4.删除map

使用delete()函数,指定key值可以方便的删除map中的k-v映射。

// map做函数参数、返回值,传引用
func MapDelete(m map[int]string,key int){
	delete(m,key)  // 删除 m 中 键值为 key的 map 元素
}


func main()  {

	MapDelete(m4,1)
	fmt.Println(m4)
}

delete()操作是安全的,即使元素不在map中也没有关系;如果查找删除失败将返回value类型对应的零值。

map输出结果依然是原来的样子,且不会有任何错误提示。

5.map的传递参数 不是传递值 而是传递引用{传递内存地址}
小练习:查找字符串中出现的次数

package main
import (
	"strings"
	"fmt"
)

func WordCountFunc(str string) map[string]int{
	s := strings.Fields(str)    // 将字符串,拆分成 字符串切片s
	m := make(map[string]int)	// 创建一个用于存储 word 出现次数的 map

	for i:=0;i< len(s);i++{
		if _,ok := m[s[i]];ok {  //ok ==true 往下走
			m[s[i]]++     //m[s[i]] = m[s[i]] + 1
		} else {
			m[s[i]] = 1   //只出现一次默认为1
		}
	}
	return m
}

func main() {
	str := "I Fuck my work and I I I I Fuck Fuck Fuck my family too"
	mRet := WordCountFunc(str)

	// 遍历map ,展示每个word 出现的次数:
	for k, v := range mRet {
		fmt.Printf("%q:%d\n", k, v)
	}
}