package main

import "fmt"

var (
	globalMap = map[string]string{}
)

func main() {
	personList := []Person{}
	personList = append(personList, Person{
		Name: "张三",
		Age:  18,
	})
	personList = append(personList, Person{
		Name: "李四",
		Age:  20,
	})

	// 如何找到李四这个对象
	for _, person := range personList {
		if person.Name == "李四" {
			// 找到了
			fmt.Println("找到李四:", person)
			break
		}
	}

	// 如果我这个切切片非常大， 上百万， 上千万
	// 通过切片查找一个元素， 效率非常低， O(n)
	// 这时可以使用 map 来优化查找效率

	// 使用map 来存储人员信息， key 是姓名， value 是 Person 对象
	personMap := map[string]Person{}
	personMap["张三"] = Person{
		Name: "张三",
		Age:  22,
	}
	personMap["李四"] = Person{
		Name: "李四",
		Age:  24,
	}
	fmt.Println("通过Map直接找到李四: ", personMap["李四"])

	/*
		1. 声明和初始化
		map[keyType]valueType
		keyType 必须是可以hash的类型， 常见的可以是 string， int， float64， bool
	*/
	// 先声明，在初始化
	var animalMap map[string]string
	// animalMap = make(map[string]string)
	// 初始化一个空的 map
	animalMap = map[string]string{}
	fmt.Println("animalMap:", animalMap)

	// 声明的同时初始化(常用, 简短声明用不了的情况, 只能用 var 声明)
	var cityMap = map[string]string{
		"北京": "北京是中国的首都",
		"上海": "上海是中国的经济中心",
		"广州": "广州是中国的南大门",
	}
	fmt.Println("cityMap:", cityMap)

	// 简短声明(最常用, 推荐)
	cityMap1 := map[string]string{
		"北京": "北京是中国的首都",
		"上海": "上海是中国的经济中心",
		"广州": "广州是中国的南大门",
	}
	fmt.Println("cityMap:", cityMap1)

	/* *	2. 访问元素
	value := map[key]
	*/
	fmt.Println("== 访问元素 ==")
	beijingDesc := cityMap1["北京"]
	fmt.Println("北京的描述是:", beijingDesc)

	/* *	3. 删除元素
	delete(map, key)
	*/
	delete(cityMap1, "广州")
	fmt.Println("删除广州后 cityMap1:", cityMap1)

	/* *	2. 增加/修改元素
	map[key] = value
	key 不存在就是新增，key 存在就是修改
	*/
	cityMap1["深圳"] = "深圳是中国的科技创新中心"
	fmt.Println("添加深圳后 cityMap1:", cityMap1)

	/*
		如何判断某个key是否存在
		comok断言:  value, ok := map[key]
		常用场景: 有了后就不修改， 没有才添加
	*/
	value, ok := cityMap1["上海"]
	if ok {
		fmt.Println("上海存在，描述是:", value)
	} else {
		fmt.Println("上海不存在")
	}

	/*
	  map的遍历
	  range iterage -> (k/indev/..., v)
	  for key, value := range map {
	  }
	*/
	fmt.Println("== map的遍历 ==")
	for key, value := range cityMap1 {
		fmt.Printf("%s 的描述是: %s\n", key, value)
	}
	// 通常只需要 key 的场景, 对象修改
	for key := range cityMap1 {
		fmt.Printf("%s 的描述是: %s\n", key, cityMap1[key])
	}

	/*
	   map 是一种引用类型, 默认值是 nil, 通过指针 指向数据(key value)c存储区(bucket)
	*/
	fmt.Println("== map 是引用类型 ==")
	m1 := map[string]int{"a": 1}
	m2 := m1 // 共享底层数据

	m2["b"] = 2
	fmt.Println(m1) // map[a:1 b:2]  m1也被修改
	fmt.Println(m2) // map[a:1 b:2]
}

type Person struct {
	Name string
	Age  int
}
