Go 语言之 Maps 详解:创建、遍历、操作和注意事项

本文涉及的产品
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
可观测监控 Prometheus 版,每月50GB免费额度
可观测可视化 Grafana 版,10个用户账号 1个月
简介: Maps用于以键值对的形式存储数据值。Maps中的每个元素都是一个键值对。Maps是一个无序且可更改的集合,不允许重复。Maps的长度是其元素的数量。您可以使用 len() 函数来查找长度。Maps的默认值是 nil。Maps保存对底层哈希表的引用。

Maps用于以键值对的形式存储数据值。Maps中的每个元素都是一个键值对。Maps是一个无序且可更改的集合,不允许重复。Maps的长度是其元素的数量。您可以使用 len() 函数来查找长度。Maps的默认值是 nil。Maps保存对底层哈希表的引用。

Go语言有多种方法来创建Maps。

使用 var 和 := 语法创建Maps

var a = map[KeyType]ValueType{
   key1:value1, key2:value2,...}
b := map[KeyType]ValueType{
   key1:value1, key2:value2,...}

示例

以下示例展示了如何在Go中创建Maps。请注意代码中和输出中的顺序。

package main
import ("fmt")

func main() {
      
  var a = map[string]string{
   "brand": "Ford", "model": "Mustang", "year": "1964"}   
  b := map[string]int{
   "Oslo": 1, "Bergen": 2, "Trondheim": 3, "Stavanger": 4}

  fmt.Printf("a\t%v\n", a)   
  fmt.Printf("b\t%v\n", b)
}

结果:

a   map[brand:Ford model:Mustang year:1964]
b   map[Bergen:2 Oslo:1 Stavanger:4 Trondheim:3]

注意:代码中定义的Maps元素的顺序与它们存储的方式不同。数据以一种能够从Maps中高效检索数据的方式存储。

使用 make() 函数创建Maps

var a = make(map[KeyType]ValueType)
b := make(map[KeyType]ValueType)

示例

以下示例展示了如何使用 make() 函数在Go中创建Maps。

package main
import ("fmt")

func main() {
      
  var a = make(map[string]string) // Maps 现在为空   
  a["brand"] = "Ford"
  a["model"] = "Mustang"
  a["year"] = "1964"
                                 // a 不再为空   
  b := make(map[string]int)   
  b["Oslo"] = 1   
  b["Bergen"] = 2   
  b["Trondheim"] = 3   
  b["Stavanger"] = 4

  fmt.Printf("a\t%v\n", a)   
  fmt.Printf("b\t%v\n", b)
}

结果:

a   map[brand:Ford model:Mustang year:1964]
b   map[Bergen:2 Oslo:1 Stavanger:4 Trondheim:3]

创建一个空Maps

创建空Maps有两种方式。一种是使用 make() 函数,另一种是使用以下语法。

var a map[KeyType]ValueType

注意:使用 make() 函数是创建空Maps的正确方式。如果以不同的方式创建空Maps并写入它,将会引发运行时错误。

示例

以下示例演示了使用 make() 函数和不使用 make() 函数声明空Maps的区别。

package main
import ("fmt")

func main() {
      
  var a = make(map[string]string)   
  var b map[string]string

  fmt.Println(a == nil)   
  fmt.Println(b == nil)
}

结果:

false
true

允许的键类型

Maps键可以是任何定义了等号运算符(==)的数据类型,包括:

  • 布尔值
  • 数字
  • 字符串
  • 数组
  • 指针
  • 结构体
  • 接口(只要动态类型支持等号运算)

不允许的键类型包括:

  • 切片
  • Maps
  • 函数

这些类型是不允许的,因为它们不支持等号运算(==)。

允许的值类型

Maps的值可以是任何类型。

访问Maps元素

您可以通过以下方式访问Maps元素:

value = map_name[key]

示例

以下示例演示了如何访问Maps元素。

package main
import ("fmt")

func main() {
      
  var a = make(map[string]string)   
  a["brand"] = "Ford"
  a["model"] = "Mustang"
  a["year"] = "1964"

  fmt.Printf(a["brand"])
}

结果:

Ford

更新和添加Maps元素

要更新或添加元素,可以使用以下方式:

map_name[key] = value

示例

以下示例演示了如何更新和添加元素到Maps中。

package main
import ("fmt")

func main() {
      
  var a = make(map[string]string)   
  a["brand"] = "Ford"
  a["model"] = "Mustang"
  a["year"] = "1964"

  fmt.Println(a)

  a["year"] = "1970" // 更新元素   
  a["color"] = "red" // 添加元素

  fmt.Println(a)
}

结果:

map[brand:Ford model:Mustang year:1964]
map[brand:Ford color:red model:Mustang year:1970]

从Maps中删除元素删除元素使用delete()函数。

语法

delete(map_name, key)

示例

package main
import ("fmt")

func main() {
   
  var a = make(map[string]string)
  a["brand"] = "Ford"
  a["model"] = "Mustang"
  a["year"] = "1964"

  fmt.Println(a)

  delete(a, "year")

  fmt.Println(a)
}

结果

map[brand:Ford model:Mustang year:1964] map[brand:Ford model:Mustang]

检查Maps中特定元素的存在 您可以使用以下语法检查Maps中是否存在特定键:

语法 val, ok := map_name[key]

如果只想检查特定键的存在,可以在val的位置使用下划线(_)。

示例

package main
import ("fmt")

func main() {
   
  var a = map[string]string{
   "brand": "Ford", "model": "Mustang", "year": "1964", "day": ""}

  val1, ok1 := a["brand"] // 检查现有键及其值
  val2, ok2 := a["color"] // 检查不存在的键及其值
  val3, ok3 := a["day"]   // 检查现有键及其值
  _, ok4 := a["model"]    // 仅检查存在的键而不检查其值

  fmt.Println(val1, ok1)
  fmt.Println(val2, ok2)
  fmt.Println(val3, ok3)
  fmt.Println(ok4)
}

结果

Ford true  false  true true

Maps是引用 Maps是对哈希表的引用。

如果两个Maps变量引用同一个哈希表,则更改一个变量的内容会影响另一个变量的内容。

示例

package main
import ("fmt")

func main() {
   
  var a = map[string]string{
   "brand": "Ford", "model": "Mustang", "year": "1964"}
  b := a

  fmt.Println(a)
  fmt.Println(b)

  b["year"] = "1970"
  fmt.Println("更改b后:")

  fmt.Println(a)
  fmt.Println(b)
}

结果

map[brand:Ford model:Mustang year:1964] map[brand:Ford model:Mustang year:1964]
更改b后:
map[brand:Ford model:Mustang year:1970] map[brand:Ford model:Mustang year:1970]

**遍历Maps **您可以使用range来遍历Maps。

示例 以下示例显示了如何遍历Maps中的元素。请注意输出中元素的顺序。

package main
import ("fmt")

func main() {
   
  a := map[string]int{
   "one": 1, "two": 2, "three": 3, "four": 4}

  for k, v := range a {
   
    fmt.Printf("%v : %v, ", k, v)
  }
}

结果

two : 2, three : 3, four : 4, one : 1,

按特定顺序遍历Maps。Maps是无序的数据结构。如果需要按特定顺序遍历Maps,则必须使用单独的数据结构来指定该顺序。

示例 以下示例演示了如何按特定顺序遍历Maps中的元素。

package main
import ("fmt")

func main() {
   
  a := map[string]int{
   "one": 1, "two": 2, "three": 3, "four": 4}

  var b []string // 定义顺序
  b = append(b, "one", "two", "three", "four")

  for k, v := range a {
    // 无序循环
    fmt.Printf("%v : %v, ", k, v)
  }

  fmt.Println()

  for _, element := range b {
    // 使用定义的顺序循环
    fmt.Printf("%v : %v, ", element, a[element])
  }
}

结果

two : 2, three : 3, four : 4, one : 1,
one : 1, two : 2, three : 3, four : 4,

最后

为了方便其他设备和平台的小伙伴观看往期文章:

微信公众号搜索:Let us Coding,关注后即可获取最新文章推送

看完如果觉得有帮助,欢迎 点赞、收藏、关注

相关文章
|
2月前
|
数据采集 Go API
Go语言实战案例:多协程并发下载网页内容
本文是《Go语言100个实战案例 · 网络与并发篇》第6篇,讲解如何使用 Goroutine 和 Channel 实现多协程并发抓取网页内容,提升网络请求效率。通过实战掌握高并发编程技巧,构建爬虫、内容聚合器等工具,涵盖 WaitGroup、超时控制、错误处理等核心知识点。
|
2月前
|
数据采集 JSON Go
Go语言实战案例:实现HTTP客户端请求并解析响应
本文是 Go 网络与并发实战系列的第 2 篇,详细介绍如何使用 Go 构建 HTTP 客户端,涵盖请求发送、响应解析、错误处理、Header 与 Body 提取等流程,并通过实战代码演示如何并发请求多个 URL,适合希望掌握 Go 网络编程基础的开发者。
|
3月前
|
JSON 前端开发 Go
Go语言实战:创建一个简单的 HTTP 服务器
本篇是《Go语言101实战》系列之一,讲解如何使用Go构建基础HTTP服务器。涵盖Go语言并发优势、HTTP服务搭建、路由处理、日志记录及测试方法,助你掌握高性能Web服务开发核心技能。
|
3月前
|
Go
如何在Go语言的HTTP请求中设置使用代理服务器
当使用特定的代理时,在某些情况下可能需要认证信息,认证信息可以在代理URL中提供,格式通常是:
275 0
|
4月前
|
JSON 编解码 API
Go语言网络编程:使用 net/http 构建 RESTful API
本章介绍如何使用 Go 语言的 `net/http` 标准库构建 RESTful API。内容涵盖 RESTful API 的基本概念及规范,包括 GET、POST、PUT 和 DELETE 方法的实现。通过定义用户数据结构和模拟数据库,逐步实现获取用户列表、创建用户、更新用户、删除用户的 HTTP 路由处理函数。同时提供辅助函数用于路径参数解析,并展示如何设置路由器启动服务。最后通过 curl 或 Postman 测试接口功能。章节总结了路由分发、JSON 编解码、方法区分、并发安全管理和路径参数解析等关键点,为更复杂需求推荐第三方框架如 Gin、Echo 和 Chi。
|
Shell Go API
Go语言grequests库并发请求的实战案例
Go语言grequests库并发请求的实战案例
|
8月前
|
存储 缓存 安全
Go 语言中的 Sync.Map 详解:并发安全的 Map 实现
`sync.Map` 是 Go 语言中用于并发安全操作的 Map 实现,适用于读多写少的场景。它通过两个底层 Map(`read` 和 `dirty`)实现读写分离,提供高效的读性能。主要方法包括 `Store`、`Load`、`Delete` 等。在大量写入时性能可能下降,需谨慎选择使用场景。
|
11月前
|
存储 负载均衡 监控
如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
在数字化时代,构建高可靠性服务架构至关重要。本文探讨了如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
230 1
|
11月前
|
Go 调度 开发者
探索Go语言中的并发模式:goroutine与channel
在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。
|
12月前
|
Java 大数据 Go
Go语言:高效并发的编程新星
【10月更文挑战第21】Go语言:高效并发的编程新星
342 7