Go 语言数据结构:Maps

Golang中的Map是一种集合类型,它用于将一个键值对映射到另一个键值对。这些键值对可以是任何可比较的类型,包括内置类型和用户定义的类型,而且每个键只能在Map中出现一次。
具体来说,Map是由一组键值对组成的无序集合。每个键必须是唯一的,而不同的键可以关联到相同的值。Map通常用于需要快速查找特定键以获取相应值的场景,例如字典或计数器。

Map 基本用法

以下是使用Map的一些基本用法:

  1. 创建Map:使用make函数创建一个Map对象,同时指定键和值的类型。
myMap := make(map[string]int)
  1. 添加元素:通过键值对的方式添加元素到Map中。
myMap["apple"] = 10
myMap["orange"] = 5
  1. 访问元素:通过键访问Map中的元素值。
fmt.Println(myMap["apple"]) // Output: 10
  1. 更新元素:通过键更新Map中的元素值。
myMap["apple"] = 15
  1. 删除元素:通过键删除Map中的元素。
delete(myMap, "orange")
  1. 遍历Map:使用for range语句遍历Map中的所有键值对,遍历是顺序是不确定的。
for key, value := range myMap {
    fmt.Println(key, value)
}

应用场景

  1. 计数器:使用Map可以轻松实现计数器功能。例如,如果需要统计一个字符串中每个字符出现的次数,可以使用一个Map来保存每个字符及其出现次数。
str := "abracadabra"
counts := make(map[rune]int)
for _, c := range str {
    counts[c]++
}
fmt.Println(counts)
// Output: map[a:5 b:2 r:2 c:1 d:1]
  1. 缓存:Map也可以用作缓存,以加快应用程序的性能。例如,在Web应用程序中,可以将从数据库中检索到的数据存储在Map中,以避免重复查询相同的数据。
type User struct {
    ID   int
    Name string
}

var cache = make(map[int]User)

func getUserByID(id int) (User, error) {
    user, ok := cache[id]
    if !ok {
        // 从数据库中查询用户信息
        user = User{ID: id, Name: "John Doe"}
        cache[id] = user
    }
    return user, nil
}
  1. 实现集合(set)数据结构:在只关心key是否存在,而不关系值的情况下可以使用 map[T]struct{} 来实现集合的效果
keySet := map[string]struct{}{"golang": {}, "java": {}}
if _, ok := keySet["golang"]; ok {
    fmt.Println("key golang exist")
} else {
    fmt.Println("key golang not exist")
}
//output key golang exist

练习:map

实现WordCount。它应该返回字符串s中每个“单词”计数的map。wc.Test函数针对所提供的函数运行一个测试套件,并打印成功或失败。你可能会用到 strings.Fields。
以下代码仅供参考

package main

import (
	"strings"

	"golang.org/x/tour/wc"
)

func WordCount(s string) map[string]int {
	res := make(map[string]int)
	words := strings.Fields(s)
	for _, word := range words {
		res[word]++
	}
	return res
}

func main() {
	wc.Test(WordCount)
}

注意事项

在使用Map时,需要注意以下几点:

  1. 并发访问:Map不是线程安全的,如果多个goroutine同时访问同一个Map,则可能会导致数据竞争和不确定结果。为了避免这种情况,可以使用sync.Mutex等方法进行加锁处理。
  2. 空指针:在声明Map时,如果没有进行初始化,则默认值为nil。如果尝试对nil map进行操作,将会产生panic。应该在声明时进行初始化或者先判断map是否为nil。
  3. 不稳定的迭代顺序:Map是无序的,因此不能保证迭代时元素的顺序。如果需要有序的集合,请使用Slice。
  4. 未初始化的值类型:当使用值类型作为Map的键时,必须确保该类型已经被初始化。例如,如果使用结构体作为键,则必须确保结构体内所有字段都被初始化。
  5. Map长度计算:不能依赖len()函数来计算Map的长度。这是因为Map的长度是动态变化的。如果需要知道Map的长度,请自己统计元素数量。
  6. Map内存泄漏:如果不再需要Map中的某个元素,请及时删除它。否则,它将占用内存,并可能导致内存泄漏。
  7. Map键类型:Map的键可以是所有可比较的类型,包括基本类型、字符串和指针。但是,不建议使用浮点数作为键,因为在计算机内部表示时可能存在精度问题。

欢迎搜索并关注 GO语言入门之路 一起学习一起进步

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Devin_S

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值