程序员的知识教程库

网站首页 > 教程分享 正文

golang2021数据格式(49)map的两种get操作

henian88 2024-09-02 16:38:37 教程分享 4 ℃ 0 评论

Go 语言中读取 map 有两种语法:带 comma 和 不带 comma。当要查询的 key 不在 map 里,带 comma 的用法会返回一个 bool 型变量提示 key 是否在 map 中;而不带 comma 的语句则会返回一个 key 类型的零值。如果 key 是 int 型就会返回 0,如果 key 是 string 类型,就会返回空字符串。

?1
? ? ?2
? ? ?3
? ? ?4
? ? ?5
? ? ?6
? ? ?7
? ? ?8
? ? ?9
? ? 10
? ? 11
? ? 12
? ? 13
? ? 14
? ? 15
? ? 16

package main

import "fmt"

func ? main() {
? ? ??????? ageMap := make(map[string]int)
? ? ??????? ageMap["qcrao"] = 18

// 不带 comma 用法
? ? ??????? age1 := ageMap["stefno"]
? ? ??????? fmt.Println(age1)

// 带 comma 用法
? ? ??????? age2, ok := ageMap["stefno"]
? ? ??????? fmt.Println(age2, ok)
? ? }

运行结果:

1
? ? 2

0
? ? 0 false

以前一直觉得好神奇,怎么实现的?这其实是编译器在背后做的工作:分析代码后,将两种语法对应到底层两个不同的函数。

1
? ? 2
? ? 3

// src/runtime/hashmap.go
? ? func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) ? unsafe.Pointer
? ? func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) ? (unsafe.Pointer, bool)

源码里,函数命名不拘小节,直接带上后缀 1,2,完全不理会《代码大全》里的那一套命名的做法。从上面两个函数的声明也可以看出差别了,mapaccess2 函数返回值多了一个 bool 型变量,两者的代码也是完全一样的,只是在返回值后面多加了一个 false 或者 true。

另外,根据 key 的不同类型,编译器还会将查找、插入、删除的函数用更具体的函数替换,以优化效率:

key 类型

查找

uint32

mapaccess1_fast32(t ? *maptype, h *hmap, key uint32) unsafe.Pointer

uint32

mapaccess2_fast32(t ? *maptype, h *hmap, key uint32) (unsafe.Pointer, bool)

uint64

mapaccess1_fast64(t ? *maptype, h *hmap, key uint64) unsafe.Pointer

uint64

mapaccess2_fast64(t ? *maptype, h *hmap, key uint64) (unsafe.Pointer, bool)

string

mapaccess1_faststr(t ? *maptype, h *hmap, ky string) unsafe.Pointer

string

mapaccess2_faststr(t ? *maptype, h *hmap, ky string) (unsafe.Pointer, bool)

这些函数的参数类型直接是具体的 uint32、unt64、string,在函数内部由于提前知晓了 key 的类型,所以内存布局是很清楚的,因此能节省很多操作,提高效率。

上面这些函数都是在文件 src/runtime/hashmap_fast.go 里。



Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表