Go语言映射内部实现及基础功能实战

目录
  • 写在前面
  • 映射的内部实现和基础功能
    • 内部实现
    • 创建和初始化
    • 使用映射
    • 在函数间传递映射

写在前面

嗯,学习GO,所以有了这篇文章博文内容为《GO语言实战》读书笔记之一主要涉及映射相关知识

你要爱就要像一个痴情的恋人那样去爱,像一个忘死的梦者那样去爱,视他人之疑目如盏盏鬼火,大胆去走你的夜路。——史铁生《病隙碎笔》

映射的内部实现和基础功能

映射是一种数据结构,是用于存储一系列无序的键值对。类比Java里的Map,Python里的字典,可以理解为以哈希值做索引,期望索引可以在一定的连续内存范围内的类似数组的数据结构。

映射里基于键来存储值。映射功能强大的地方是,能够基于键快速检索数据。键就像索引一样,指向与该键关联的值。

内部实现

映射是一个集合,可以使用类似处理数组和切片的方式迭代映射中的元素。但映射是无序的集合,无序的原因是映射的实现使用了散列表.

映射的散列表包含一组桶。

在存储、删除或者查找键值对的时候,所有操作都要先选择一个桶。把操作映射时指定的键传给映射的散列函数,就能选中对应的桶。

这个散列函数的目的是生成一个索引,这个索引最终将键值对分布到所有可用的桶里。对 Go 语言的映射来说,生成的散列键的一部分,具体来说是低位(LOB),被用来选择桶。

桶的内部实现。映射使用两个数据结构来存储数据,

第一个是数组,内部存储用于选择桶的散列键的高八位值。用于区分每个键值对要存在桶里的那一项。第二个是字节数组,用于存储键值对。该字节数组先依次存储了这个桶里所有的键,之后依次存储了这个桶里所有的值。实现这种键值对的存储方式目的在于减少每个桶所需的内存。

映射存储的增加,索引分布越均匀,访问键值对的速度就越快,随着映射存储的增加,索引分布越均匀,访问键值对的速度就越快。映射通过合理数量的桶来平衡键值对的分布

创建和初始化

Go 语言中有很多种方法可以创建并初始化映射,可以使用内置的make 函数,也可以使用映射字面量。

package main
import (
	"fmt"
)
func main() {
	// 创建一个映射,键的类型是 string,值的类型是 int
	dict := make(map[string]int)
	// 创建一个映射,键和值的类型都是 string
	// 使用两个键值对初始化映射
	dict_ := map[string]string{"Red": "#da1337", "Orange": "#e95a22"}
	fmt.Println(dict)
	fmt.Print(dict_)
}
======
map[]
map[Orange:#e95a22 Red:#da1337]

创建映射时,更常用的方法是使用映射字面量。映射的初始长度会根据初始化时指定的键值对的数量来确定。

映射的键可以是任何值。这个值的类型可以是内置的类型,也可以是结构类型,只要这个值可以使用==运算符做比较

切片、函数以及包含切片的结构类型由于具有引用语义,不能作为映射的键,使用这些类型会造成编译错误

package main
import (
	"fmt"
)
func main() {
	// 创建一个映射,使用字符串切片作为映射的键
	dict := map[[]string]int{}
	fmt.Println(dict)
}
====
[Running] go run "d:\GolandProjects\code-master\demo\hello.go"
# command-line-arguments
demo\hello.go:10:45: duplicate key "Red" in map literal
	previous key at demo\hello.go:10:28
[Done] exited with code=2 in 0.902 seconds

声明一个存储字符串切片的映射

// 创建一个映射,使用字符串切片作为值
dict := map[int][]string{}

使用映射

键值对赋值给映射,是通过指定适当类型的键并给这个键赋一个值来完成的

为映射赋值

// 创建一个空映射,用来存储颜色以及颜色对应的十六进制代码
colors := map[string]string{}
// 将 Red 的代码加入到映射
colors["Red"] = "#da1337"

可以通过声明一个未初始化的映射来创建一个值为nil的映射,不能用于存储键值对.

// 创建一个空映射,用来存储颜色以及颜色对应的十六进制代码
colors := map[string]string{}
// 将 Red 的代码加入到映射
colors["Red"] = "#da1337"

从映射取值时有两个选择:

第一个选择是,可以同时获得值,以及一个表示这个键是否存在的标志,

从映射获取值并判断键是否存在

// 获取键 Blue 对应的值
value := colors["Blue"]
// 这个键存在吗?
if value != "" {
fmt.Println(value)
}

另一个选择是,只返回键对应的值,然后通过判断这个值是不是零值来确定键是否存在

从映射获取值,并通过该值判断键是否存在

// 获取键 Blue 对应的值
value := colors["Blue"]
// 这个键存在吗?
if value != "" {
fmt.Println(value)
}

在Go语言里,通过键来索引映射时,即便这个键不存在也总会返回一个值。在这种情况下,返回的是该值对应的类型的零值

迭代映射里的所有值和迭代数组或切片一样,使用关键字 range

使用range 迭代映射

// 创建一个映射,存储颜色以及颜色对应的十六进制代码colors := map[string]string{<!--{C}%3C!%2D%2D%20%2D%2D%3E-->"AliceBlue": "#f0f8ff","Coral": "#ff7F50","DarkGray": "#a9a9a9","ForestGreen": "#228b22",}// 显示映射里的所有颜色for key, value := range colors {<!--{C}%3C!%2D%2D%20%2D%2D%3E-->fmt.Printf("Key: %s Value: %s\n", key, value)}// 创建一个映射,存储颜色以及颜色对应的十六进制代码
colors := map[string]string{
"AliceBlue": "#f0f8ff",
"Coral": "#ff7F50",
"DarkGray": "#a9a9a9",
"ForestGreen": "#228b22",
}
// 显示映射里的所有颜色
for key, value := range colors {
	fmt.Printf("Key: %s Value: %s\n", key, value)
}

想把一个键值对从映射里删除,就使用内置的delete 函数

从映射中删除一项

// 删除键为 Coral 的键值对delete(colors, "Coral")// 显示映射里的所有颜色for key, value := range colors {<!--{C}%3C!%2D%2D%20%2D%2D%3E-->fmt.Printf("Key: %s Value: %s\n", key, value)}// 删除键为 Coral 的键值对
delete(colors, "Coral")
// 显示映射里的所有颜色
for key, value := range colors {
	fmt.Printf("Key: %s Value: %s\n", key, value)
}

在函数间传递映射

在函数间传递映射并不会制造出该映射的一个副本。实际上,当传递映射给一个函数,并对这个映射做了修改时,所有对这个映射的引用都会察觉到这个修改,这个特性和切片类似,保证可以用很小的成本来复制映射

package mainimport ("fmt")func main() {<!--{C}%3C!%2D%2D%20%2D%2D%3E-->// 创建一个映射,存储颜色以及颜色对应的十六进制代码colors := map[string]string{<!--{C}%3C!%2D%2D%20%2D%2D%3E-->"AliceBlue": "#f0f8ff","Coral": "#ff7F50","DarkGray": "#a9a9a9","ForestGreen": "#228b22",}// 显示映射里的所有颜色for key, value := range colors {<!--{C}%3C!%2D%2D%20%2D%2D%3E-->fmt.Printf("Key: %s Value: %s\n", key, value)}fmt.Println("调用函数来移除指定的键")// 调用函数来移除指定的键removeColor(colors, "Coral")// 显示映射里的所有颜色for key, value := range colors {<!--{C}%3C!%2D%2D%20%2D%2D%3E-->fmt.Printf("Key: %s Value: %s\n", key, value)}}// removeColor 将指定映射里的键删除func removeColor(colors map[string]string, key string) {<!--{C}%3C!%2D%2D%20%2D%2D%3E-->delete(colors, key)}package main

import (
	"fmt"
)
func main() {
	// 创建一个映射,存储颜色以及颜色对应的十六进制代码
	colors := map[string]string{
		"AliceBlue":   "#f0f8ff",
		"Coral":       "#ff7F50",
		"DarkGray":    "#a9a9a9",
		"ForestGreen": "#228b22",
	}
	// 显示映射里的所有颜色
	for key, value := range colors {
		fmt.Printf("Key: %s Value: %s\n", key, value)
	}
	fmt.Println("调用函数来移除指定的键")
	// 调用函数来移除指定的键
	removeColor(colors, "Coral")

	// 显示映射里的所有颜色
	for key, value := range colors {
		fmt.Printf("Key: %s Value: %s\n", key, value)
	}
}
// removeColor 将指定映射里的键删除
func removeColor(colors map[string]string, key string) {
	delete(colors, key)
}
[Running] go run "d:\GolandProjects\code-master\demo\hello.go"
Key: Coral Value: #ff7F50
Key: DarkGray Value: #a9a9a9
Key: ForestGreen Value: #228b22
Key: AliceBlue Value: #f0f8ff
调用函数来移除指定的键
Key: AliceBlue Value: #f0f8ff
Key: DarkGray Value: #a9a9a9
Key: ForestGreen Value: #228b22
[Done] exited with code=0 in 1.419 seconds

映射的增长没有容量或者任何限制。同时内置函数 len可以用来获取切片或者映射的长度。但是内置函数 cap只能用于切片。

以上就是Go语言映射内部实现及基础功能实战的详细内容,更多关于Go语言映射内部实现和基础功能的资料请关注我们其它相关文章!

(0)

相关推荐

  • GO语言映射(Map)用法分析

    本文实例讲述了GO语言映射(Map)用法.分享给大家供大家参考.具体如下: 映射是一种内置的数据结构,用来保存键值对的无序集合. (1)映射的创建 make ( map [KeyType] ValueType, initialCapacity ) make ( map [KeyType] ValueType ) map [KeyType ] ValueType {} map [KeyType ] ValueType { key1 : value1, key2: value2, ... , key

  • Go语言实现一个简单的并发聊天室的项目实战

    目录 写在前面 并发聊天服务器 具体代码 服务端 客户端 总结 写在前面 Go语言在很多方面天然的具备很多便捷性,譬如网络编程,并发编程.而通道则又是Go语言实现并发编程的重要工具,因为其承担着通道之间互相通信的重任.并且因为其本身就是并发安全的,所以在某些场景下是非常好用的. 并发聊天服务器 这里主要是实现一个简单的并发聊天服务器.首先,客户端可以在服务器中注册自己的信息(登录以及退出),客户端发出的所有的信息由服务器向各个客户端进行转发,或者换句话说是广播. 具体代码 服务端 说的再多,没有

  • go语言通过反射创建结构体、赋值、并调用对应的操作

    我就废话不多说了,大家还是直接看代码吧~ package main import ( "fmt" "reflect" "testing" ) type Call struct { Num1 int Num2 int } func (call Call) GetSub(name string){ fmt.Printf("%v 完成了减法运算,%v - %v = %v \n", name, call.Num1, call.Num2

  • 浅析Go语言编程当中映射和方法的基本使用

    映射 Go编程提供的一个重要的数据类型就是映射,唯一映射一个键到一个值.一个键要使用在以后检索值的对象.给定的键和值,可以在一个Map对象存储的值.值存储后,您可以使用它的键检索. 定义映射 必须使用make函数来创建一个映射. 复制代码 代码如下: /* declare a variable, by default map will be nil*/ var map_variable map[key_data_type]value_data_type /* define the map as

  • Go语言映射内部实现及基础功能实战

    目录 写在前面 映射的内部实现和基础功能 内部实现 创建和初始化 使用映射 在函数间传递映射 写在前面 嗯,学习GO,所以有了这篇文章博文内容为<GO语言实战>读书笔记之一主要涉及映射相关知识 你要爱就要像一个痴情的恋人那样去爱,像一个忘死的梦者那样去爱,视他人之疑目如盏盏鬼火,大胆去走你的夜路.——史铁生<病隙碎笔> 映射的内部实现和基础功能 映射是一种数据结构,是用于存储一系列无序的键值对.类比Java里的Map,Python里的字典,可以理解为以哈希值做索引,期望索引可以在一

  • C语言实现手写Map(全功能)的示例代码

    目录 为啥需要Map结构 主流Map结构 数组+链表的Map 结构 hash函数 创建Map集合 扩容基数 扩容Map集合 给Map集合添加元素 打印Map集合 获取Map集合中的指定元素 判断键是否存在 判断值是否存在 删除Map集合中的指定元素 修改Map集合中的指定元素 迭代器 获取所有的key 获取所有的value 复制一个Map 将一个map集合合并到另一个map集合里 合并两个Map集合,返回一个新的Map集合 差集 交集 补集 并集 清除Map 为啥需要Map结构 假设,数据很少,

  • 如何用C写一个web服务器之基础功能

    服务器架构 目标架构 以 nginx 的思想来考虑本服务器架构,初步考虑如下图: 当然 php 进程也可以替换为其他的脚本语言,可以更改源码中的 command 变量实现. 服务器有一个 master 进程,其有多个子进程为 worker 进程,master 进程受理客户端的请求,然后分发给 worker 进程,worker 进程处理 http 头信息后将参数传递给 php 进程处理后,将结果返回到上层,再响应给客户端. 也考虑过使用 php-fpm 的 worker 进程池方式,那样的话 ph

  • C语言超详细文件操作基础下篇

    目录 一.文件的顺序读写 1.格式化的输出函数(fprintf) 2.格式化的输入函数(fscanf) 3.二进制读写 1.二进制输出函数(fwrite) 2.二进制输入函数 3.scanf,fscanf,sscanf.printf,fprintf,sprintf的区别 二.文件的随机读写 1.fseek函数 2.ftell函数 3.rewind函数 三.被错误使用的feof 总结 一.文件的顺序读写 兄弟们,上一章只介绍到了如何把单个的字符或者字符串如何写到文件里或者从文件中读取,文件的顺序读

  • C语言超详细文件操作基础上篇

    目录 一.为什么使用文件 二.什么是文件 1.什么是数据文件 2.什么是程序文件 3.文件名 三.文件的打开和关闭 1文件指针: 2.打开和关闭文件函数 (1)打开文件函数: (2)关闭文件函数 四.文件的顺序读写 1.写文件(fputc,操作一个字符) 2.读文件(fgetc,操作一个字符) 3.写文件(fputs,操作字符串) 4.读文件(fgets,操作字符串) 一.为什么使用文件 为了更好的把信息记录下来,对数据进行持久化的保存,这个时候我们就可以把数据写到文件里面去,使用文件我们可以将

  • C语言函数指针数组实现计算器功能

    目录 一.概念 二.用途 三.案例:计算器 (1)基础代码编译: (2)使用函数指针数组的实现: 一.概念 数组:一个存放相同类型数据的存储空间. int arr[10]; //数组arr的每个元素是int 指针数组:一个存放指针的数组. int* arr[10]; //数组arr的每个元素是int* 函数指针:一个指向函数的指针,一般用函数名表示. int Add(int x, int y) { return x + y; } int main() { int arr[10] = { 1, 2

  • Go语言实现操作MySQL的基础知识总结

    目录 前言 下载依赖 使用 MySQL 驱动 SetMaxOpenConns SetMaxIdleConns 操作 前言 MySQL 是目前开发中最常见的关系型数据库,也是程序员打交道最多的数据库. 使用 Go 语言进行操控数据库需要使用 Go 自带database/sql和驱动go-sql-driver/mysql来实现.这篇文章主要总结一下怎么使用Go语言操作MySql数据库,需要的朋友可以参考以下内容,希望对大家有帮助. 下载依赖 database/sql是Go操作数据库的标准库之一,它提

  • php实现文件管理与基础功能操作

    文件的基本操作 先来看一下PHP文件基础操作,请看强大注释 <body> <?php var_dump(filetype("./img/11.png")); //判断返回得是文件还是目录,返回sile为文件,dir为目录(文件夹) var_dump(is_dir("./img/11.png")); //判断给的文件是不是一个目录,目录为ture,文件为false var_dump(is_file("./img")); //判断是

  • PHP实现类似于C语言的文件读取及解析功能

    本文实例讲述了PHP实现类似于C语言的文件读取及解析功能.分享给大家供大家参考,具体如下: $log_file_name = 'D:/static/develop/kuai_zhi/acagrid.com/public/Logs/'.date('Ym').'/'.date('d').'_error.log'; //$log_file_name = 'D:/static/develop/kuai_zhi/acagrid.com/public/Logs/201701/19_error.log'; i

随机推荐