Go的map结构体

1、map的初始化

package main

import "fmt"

func main() {
	var m map[int]string = map[int]string{1: "张三", 2: "李四", 3: "小红"}
	m1 := map[int]string{}
	m2 := make(map[string]int, 10)
	m2["张三"] = 12
	m2["李四"] = 13
	fmt.Println(m)
	fmt.Println(m1)
	fmt.Println(m2)
	fmt.Println("m2 len == ", len(m2)) //len()返回的是map中已有的键值对个数。
}

输出结果:

map[1:张三 2:李四 3:小红]
map[]               
map[张三:12 李四:13]
m2 len ==  2    

2、map键与值

package main

import "fmt"

func main() {
	var m map[int]string = map[int]string{1: "张三", 2: "李四", 3: "小红"}
	fmt.Println(m[2])
	value, ok := m[4]
	if ok {
		fmt.Println(value)
	} else {
		fmt.Println("不存在")
	}

	for key, value := range m {
		fmt.Println("key == ", key, ", value == ", value)
	}

}

输出结果:

李四
不存在                    
key ==  1 , value ==  张三
key ==  2 , value ==  李四
key ==  3 , value ==  小红

3、map通过key删除某个值

package main

import "fmt"

func main() {
	var m map[int]string = map[int]string{1: "张三", 2: "李四", 3: "小红"}
	delete(m, 2)
	fmt.Println(m)
}

输出结果:

map[1:张三 3:小红]

4、map作为函数参数

package main

import "fmt"

func main() {
	var m map[int]string = map[int]string{1: "张三", 2: "李四", 3: "小红"}
	deleteMap(m)
	printMap(m)
}

func printMap(m map[int]string) {
	for v, k := range m {
		fmt.Println(v, " ", k)
	}
}

func deleteMap(m map[int]string) {
	delete(m, 2)
}

输出结果:

1   张三
3   小红

5、案例

案例:通过键盘输入一个英文字符串 统计每个字母出现的次数

package main

import "fmt"

func main() {
	var str string
	fmt.Scan(&str)
	//将字符串转成切片
	slice := []byte(str)

	//定义map进行数据存储
	//map[字符]个数
	m := make(map[byte]int)

	//var ch byte
	for i := 0; i < len(slice); i++ {
		//ch = slice[i]
		//m[ch] += 1
		//将slice切片的中的元素作为m中的key
		m[slice[i]]++
	}

	for k, v := range m {
		fmt.Printf("%c:%d\n", k, v)
	}

}

输入:asssxxsasa
结果:

a:3
s:5
x:2

### Map 结构体的定义 在 Go 中,`map` 并不是一个真正的结构体,而是内置的数据类型之一。它的本质是一个哈希表(hash table),用于存储键值对(key-value pairs)。Map 的定义形式如下: ```go map[keyType]valueType ``` 其中 `keyType` 是键的类型,`valueType` 是值的类型。键必须是可以比较的类型(如整数、字符串、指针等),而值可以是任意类型。 关于 `map` 的具体实现细节,在底层是由运行时库管理的一个复杂数据结构完成的[^1]。Go 官方并未公开其实现的具体源码逻辑,但可以通过分析得知其内部采用了拉链法(chaining)处理冲突,并且动态调整容量以优化性能。 --- ### Map 的使用方法 #### 1. **创建** 可以通过字面量或者 `make` 函数创建一个 map: ```go m := make(map[string]int) n := map[string]string{"one": "uno", "two": "dos"} ``` #### 2. **赋值与访问** 通过键来设置或获取对应的值: ```go m["answer"] = 42 // 设置值 fmt.Println(m["answer"]) // 获取值 ``` 如果尝试访问不存在的键,则返回对应值类型的零值。例如对于 `int` 类型,默认会返回 `0`。 #### 3. **删除元素** 利用内置函数 `delete` 可移除指定键及其关联的值: ```go delete(m, "answer") // 删除 key "answer" ``` #### 4. **判断是否存在某键** 当不确定某个键是否存在时,可采用双变量的形式读取: ```go value, exists := m["answer"] if !exists { fmt.Println("Key does not exist.") } ``` 这里第二个返回值表明该键是否存在于映射中。 #### 5. **遍历** 借助 `for-range` 循环迭代所有的键值对: ```go for k, v := range n { fmt.Printf("%s -> %s\n", k, v) } ``` 以上操作均基于官方文档以及常见实践总结得出结论[^2]。 --- ### Map 的实现细节 尽管开发者无需关心太多底层机制即可高效运用 maps ,理解这些原理有助于编写更优代码 。以下是几个重要方面 : - **内存分配**: 初始状态下 , 当调用 `make()` 构造一个新的空闲状态下的 hash 表时候 , 如果未提供初始大小参数则默认初始化较小固定尺寸 . 随着不断插入新项目达到一定负载因子之后触发扩容过程 . - **扩容策略**: 扩展过程中并非简单复制原数组到更大空间里去 ; 而是对旧桶重新散列分布至新的两倍长度的新桶集合之中 . 此外为了减少一次性迁移带来的开销影响效率问题 , 整个转移动作被拆分成多次逐步完成 . 上述特性来源于标准库中的 runtime/map.go 文件解析结果[^3]. --- ### 示例代码展示如何自定义封装带接收者的 map 方法 虽然严格意义上讲 go 不允许直接为基本类型比如 slice 或者 map 添加额外行为方式像其他 oo 编程那样做继承之类的事情;但是我们仍然能够模仿这种模式设计辅助工具类来进行扩展功能演示: ```go package main import ( "fmt" ) // 自定义了一个包含 map 成员字段结构体 type MyMap struct { data map[string]int } // 初始化构造器 func NewMyMap() *MyMap { return &MyMap{ data: make(map[string]int), } } // 提供 set 方法 func (mm *MyMap) Set(key string, value int) { mm.data[key] = value fmt.Printf("Inserted (%s:%d)\n", key, value) } // 提供 get 方法 func (mm *MyMap) Get(key string) (int, bool) { val, ok := mm.data[key] if !ok { fmt.Println("Not Found!") } else { fmt.Printf("Retrieved (%s:%d)\n", key, val) } return val, ok } func main() { myMap := NewMyMap() // 测试 insert 功能 myMap.Set("apple", 5) // 测试 retrieve 功能 num, found := myMap.Get("banana") if !found { fmt.Println("No bananas available.") } else { fmt.Println("Bananas count:", num) } } ``` 此例子展示了怎样把原始简单的 map 升级成具备更多特性的版本[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值