Go 语言入门很简单 -- 8. Go Maps #私藏项目实操分享#

简介: Go 语言入门很简单 -- 8. Go Maps #私藏项目实操分享#

映射

映射也是 Go 内置的数据结构,用于存储键值对的无序集合。

也被称为关联数组、哈希表字典。类似与查字典,映射用于通过关键键查找关联的值。键是唯一的,键对应的值可以通过键来获取、更新或删除。 可以利用映射来检测一个键是否已经存在。值存储后,可以通过引用相关的键来调用映射的值。

image.png

映射的定义

以下是 Go 中映射的定义:

var x map[string] int

映射类型由关键字 map 表示,后跟括号中的类型,最后是类型。

image.png

映射的散列表包含一组桶。在存储、删除或查找键值对的时候,所有的操作要先选择一个桶。把操作映射时指定的键传给映射的散列函数,就能选中对应的桶。这个散列函数的目的是生成一个索引,这个索引最终将键值对分布到所有可用的桶里。

如上图所示,桶的内部实现。映射使用两个数据结构来存储数据:

  • 第一个数据结构是一个数组,内部存储的是用于选择桶的散列值的高八位值。这个数组用于区分每个键值对要存在哪个桶里。
  • 第二个数据结构是一个字节数组,用于存储键值对。改字节数组依次存储了这个桶里所有的键,之后一次存储了这个桶里所有的值。

这种键值对的存储方法的目的:减少每个桶里所需的内存

image.png

类似于数组和切片,同样可以使用中括号 [] 来访问映射,

package main
import "fmt"
func main() {
    my_map := make(map[string]int)  // 创建一个从string到int的
    my_map["小李"] = 18
    my_map["老张"] = 50
    fmt.Println(my_map)
    fmt.Printf("老张今年%d岁.", my_map["老张"])
}

运行该代码,结果为:

map[小李:18 老张:50]
老张今年50岁.

也可以使用 map 字面量来创建一个带初始化键值对元素的映射:

ages := map[string]int{
    "小李": 18,
    "老张": 30,
    "老罗": 45,
}

可以使用内置函数 delete 来从字典中根据键移除一个元素:

delete(ages, "老张") // 删除 ages["老张"]

映射遍历

可以使用 for...range 循环来遍历 map 中所有的键和对应的值,就像遍历 slice 一样。在每次迭代中获得键值对,但是每一次遍历可能会不一样,即迭代顺序是随机的。

package main
import "fmt"
func main() {
    ages := map[string]int{
        "小李": 18,
        "老张": 30,
        "老罗": 45,
    }
    for name, age := range ages {
        fmt.Println(name, age)
    }
}

运行结果为:

小李 18
老张 30
老罗 45

映射排序

映射中元素的迭代顺序是不固定的,不同的实现方法会使用不同的散列算法,得到不同的元素顺序。如果需要按照某种顺序来遍历映射中的元素,可以显式的给键排序。

像上述的例子中,键是字符串类型,可以使用 sort 包中的 Strings 函数来进行键的排序:

package main
import (
    "fmt"
    "sort"
)
func main() {
    var names []string
    ages := map[string]int{
        "小李": 18,
        "老张": 30,
        "老罗": 45,
    }
    for name, age := range ages {
        fmt.Println(name, age)
    }
    fmt.Println("--- 排序后 ---")
    for name := range ages {
        names = append(names, name)
    }
    sort.Strings(names)
    for _, name := range names {
        fmt.Printf("%s\t%d\n", name, ages[name])
    }
}

运行后,得到结果:

老罗 45
小李 18
老张 30
--- 排序后 ---
小李  18
老张  30
老罗  45

映射是引用类型

映射也是引用类型。 将映射分配给新变量时,它们都引用相同的底层数据结构。 因此,一个变量更改,对另一个变量也会被相应的更改。 例子如下:

package main
import (
    "fmt"
)
func main() {
    var my_map = map[int]string{
        64: "new Zealand",
        3:  "Russia",
        44: "UK",
        61: "Australia",
        81: "Japan",
        91: "India",
    }
    fmt.Println("初始 map: ", my_map)
    // 赋值给新 map
    new_map := my_map
    // 新 map 中进行添加
    new_map[86] = "China"
    new_map[33] = "France"
    fmt.Println("new_map: ", new_map)
    fmt.Println("修改后的初始 map: \n", my_map)
}

运行结果:

初始 map:  map[3:Russia 44:UK 61:Australia 64:new Zealand 81:Japan 91:India]
new_map:  map[3:Russia 33:France 44:UK 61:Australia 64:new Zealand 81:Japan 86:China 91:India]
修改后的初始 map: 
 map[3:Russia 33:France 44:UK 61:Australia 64:new Zealand 81:Japan 86:China 91:India]

总结

Map 是 Golang 中键值对的无序集合。键在映射中是唯一的,但值可能不是。它被广泛使用,因为它提供了可以在键的帮助下检索、更新或删除的快速查找和值。

在 Golang 中,映射也称为关联数组、哈希表或字典。 映射用于通过其关联的键查找值。

一个映射的零值是 nil 并且一个 nil 映射没有键。 因此,任何将键添加到 nil 映射的尝试都将导致运行时错误。

在 Go 中,您可以使用内置的 make() 函数初始化映射。 它就会返回一个已初始化并可随时使用的映射。

可以使用 Go 编程语言中 for...range 循环的范围形式迭代映射。

在 Golang 中,映射是一个无序集合,因此,不能保证每次迭代时映射的迭代顺序都相同。因此,如果您多次运行任何程序,您将获得不同顺序的结果。

Maps 是 Golang 中的引用类型。 将映射分配给新变量时,它们都引用相同的底层数据结构。 因此,一个变量所做的更改,另一个变量相应会被更改。


相关文章
|
2月前
|
算法 Java Go
【GoGin】(1)上手Go Gin 基于Go语言开发的Web框架,本文介绍了各种路由的配置信息;包含各场景下请求参数的基本传入接收
gin 框架中采用的路优酷是基于httprouter做的是一个高性能的 HTTP 请求路由器,适用于 Go 语言。它的设计目标是提供高效的路由匹配和低内存占用,特别适合需要高性能和简单路由的应用场景。
241 4
|
3月前
|
Linux Go iOS开发
Go语言100个实战案例-进阶与部署篇:使用Go打包生成可执行文件
本文详解Go语言打包与跨平台编译技巧,涵盖`go build`命令、多平台构建、二进制优化及资源嵌入(embed),助你将项目编译为无依赖的独立可执行文件,轻松实现高效分发与部署。
|
2月前
|
Cloud Native 安全 Java
Go语言深度解析:从入门到精通的完整指南
🌟蒋星熠Jaxonic,Go语言探索者。深耕云计算、微服务与并发编程,以代码为笔,在二进制星河中书写极客诗篇。分享Go核心原理、性能优化与实战架构,助力开发者掌握云原生时代利器。#Go语言 #并发编程 #性能优化
406 43
Go语言深度解析:从入门到精通的完整指南
|
3月前
|
Cloud Native 安全 Java
Go语言深度解析:从入门到精通的完整指南
🌟 蒋星熠Jaxonic,执着的星际旅人,用Go语言编写代码诗篇。🚀 Go语言以简洁、高效、并发为核心,助力云计算与微服务革新。📚 本文详解Go语法、并发模型、性能优化与实战案例,助你掌握现代编程精髓。🌌 从goroutine到channel,从内存优化到高并发架构,全面解析Go的强大力量。🔧 实战构建高性能Web服务,展现Go在云原生时代的无限可能。✨ 附技术对比、最佳实践与生态全景,带你踏上Go语言的星辰征途。#Go语言 #并发编程 #云原生 #性能优化
|
5月前
|
JSON 中间件 Go
Go语言实战指南 —— Go中的反射机制:reflect 包使用
Go语言中的反射机制通过`reflect`包实现,允许程序在运行时动态检查变量类型、获取或设置值、调用方法等。它适用于初中级开发者深入理解Go的动态能力,帮助构建通用工具、中间件和ORM系统等。
306 63
|
6月前
|
测试技术 程序员 Go
Go语言测试简明指南:深度解读go test命令
总的来说,go test是 Go 语言中一个强而有力的工具,每个 Go 程序员都应该掌握并把它融入到日常的开发和调试过程中。就像是一个眼镜过滤出的太阳,让我们在宽阔的代码海洋中游泳,而不是淹没。用好它,让我们的代码更健壮,让我们的生产力更强效。
527 23
|
6月前
|
数据可视化 测试技术 Go
Go 语言测试与调试:`go test` 工具用法
`go test` 是 Go 语言内置的测试工具,支持单元测试、基准测试、示例测试等功能。本文详解其常用参数、调试技巧及性能测试命令,并提供实际项目中的应用示例与最佳实践。
|
10月前
|
存储 缓存 安全
Go 语言中的 Sync.Map 详解:并发安全的 Map 实现
`sync.Map` 是 Go 语言中用于并发安全操作的 Map 实现,适用于读多写少的场景。它通过两个底层 Map(`read` 和 `dirty`)实现读写分离,提供高效的读性能。主要方法包括 `Store`、`Load`、`Delete` 等。在大量写入时性能可能下降,需谨慎选择使用场景。
|
存储 负载均衡 监控
如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
在数字化时代,构建高可靠性服务架构至关重要。本文探讨了如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
289 1
|
Go 调度 开发者
探索Go语言中的并发模式:goroutine与channel
在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。