当前位置: 首页 > news >正文

深入理解 Go 语言并发 map 安全使用

        对于哈希表(hash table) 这种数据结构,它实现的就是 key-value 之间的映射关系,主要提供的方法包括 Add、Lookup、Delete 等。因为哈希表是一种基础的数据结构,每个 key 都会有一个唯一的索引值,通过索引可以很快地找到对应的值,所以使用它进行数据的插入和读取是很快的。Go 语言本身就内建了这样一个数据结构,也就是 map 数据类型。

1. 线程安全的 map

        Go 语言内建的 map 类型如下:

map[k]V

        其中,key 类型的 K 必须是可比较的(comparable),也就是可以通过 == 和 != 操作符进行比较;V 的值和类型无所谓,它可以是任意类型,或者为 nil。在 Go 语言中,bool、整数、浮点数、复数、字符串、指针、Channel、接口都是可比较的,包含可比较元素的 struct 和数组也是可比较的,而 sliece、map、函数值都是不可比较的。

        那么,上面这些可比较的数据类型都适合作为 map 的 key 的类型吗?答案是否定的。在通常情况下,我们会选择内建的基本类型,比如整数、字符串作为 key 的类型,因为这样最方便,值不可变,也不容易出错。而使用 struct 作为 key 的类型,如果 struct 的某个字段值被修改了,那么在查询 map 时将无法获取它添加的值。

type mapKey struct {key int
}func mail() {var m = make(map[mapKey]string)var key = mapKey{10}m[key] = "hello"fmt.Printf("m[key]=%s\n", m[key])// 修改 key 的字段值后再次查询map,将无法获取刚才添加的值key.key = 100fmt.Printf("再次查询m[key]=%s\n", m[key])
}

        那该怎么办呢?如果使用 struct 作为 key 的类型,则要保证 struct 对象在逻辑上是不可变的,这样才能保证 map 的逻辑没有问题。以上就是在选择 key 类型时需要注意的地方。

         接下来,我们看一下使用 map[key] 函数时需要注意的一个知识点。在 Go 语言中, map[key] 函数的返回结果可以是一个值,也可以是两个值,这是容易让人迷惑的地方。原因在于:如果获取一个不存在的 key 对应的值,则会返回零值。为了区分真正的零值和 key 不存在这两种情况,可以根据第二个返回值来判断,如下面代码:

func main(){var m = make(map[string]int)m ["a"] = 0fmt.Printf("a=%d;b=%d\n",m["a"],m["b"])av,aexisted := m["a"]bv,bexisted := m["b"]fmt.Printf("a=%d,existed:%t;b=%d,existed:%t\n",av,aexisted,bv,bexisted)
}

        将对 map 的遍历故意设置成无序的&#

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【SpringBoot3】双向实时通讯 websocket
  • 第二章 方法与方法重载
  • 在HFSS中对曲线等结构进行分割(Split)
  • ubuntu 安装两个nginx实例时的坑,非默认nginx实例配置修改总也不生效的问题
  • HTML及CSS面试题4
  • 66_1JSON【浏览器中处理JSON、Java中处理JSON(FastJSON、Jackson)】、Java中的bean
  • XML外部实体注入
  • 使用docxtemplater-image-module-free时支持动态获取图片大小
  • SpringBoot:将单体项目拆分成微服务项目
  • 【PGCCC】pg_bestmatch.rs:使用 BM25 提升您的 PostgreSQL 文本查询#PCA
  • Windows下添加开机启动项
  • Vue.js 中的指令(Vue自定义指令)
  • 在小程序添加公司官网访问
  • 使用 Vue 2 搭建后台管理系统
  • 学习计算机网络(五)——ICMP协议
  • Android开发 - 掌握ConstraintLayout(四)创建基本约束
  • android图片蒙层
  • Git初体验
  • node 版本过低
  • python_bomb----数据类型总结
  • RedisSerializer之JdkSerializationRedisSerializer分析
  • unity如何实现一个固定宽度的orthagraphic相机
  • Vue2.x学习三:事件处理生命周期钩子
  • 力扣(LeetCode)22
  • 悄悄地说一个bug
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 最简单的无缝轮播
  • Java数据解析之JSON
  • ​Redis 实现计数器和限速器的
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • #laravel 通过手动安装依赖PHPExcel#
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • (+4)2.2UML建模图
  • (1)Nginx简介和安装教程
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (算法)Travel Information Center
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (原创)攻击方式学习之(4) - 拒绝服务(DOS/DDOS/DRDOS)
  • (转)jdk与jre的区别
  • (转)linux自定义开机启动服务和chkconfig使用方法
  • (转)Windows2003安全设置/维护
  • (转载)Google Chrome调试JS
  • (总结)Linux下的暴力密码在线破解工具Hydra详解
  • ***监测系统的构建(chkrootkit )
  • .net core 的缓存方案
  • .NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式
  • .NetCore发布到IIS
  • .NET开发人员必知的八个网站
  • .NET开源项目介绍及资源推荐:数据持久层 (微软MVP写作)
  • ::什么意思
  • @ResponseBody