《Go小技巧易错点100例》第三十二篇

news2025/5/12 19:39:42

本期分享:

1.sync.Map的原理和使用方式

2.实现有序的Map

sync.Map的原理和使用方式

sync.Map的底层结构是通过读写分离无锁读设计实现高并发安全:

1)双存储结构

包含原子化的 read(只读缓存,无锁快速访问)和加锁的 dirty(写入缓冲区)

2)读优先

读取时先尝试无锁访问 read,未命中时加锁访问 dirty 并记录未命中次数

3)动态升级

当未命中次数超过 dirty 长度时,将 dirty 原子替换为新的 read

4)延迟删除

删除操作仅标记数据状态(expunged),实际清理在 dirty 升级时批量处理

5)值原子化

通过 entry 指针的原子操作实现值更新的无锁化,适用于读多写少的高并发场景。

请在此添加图片描述

部分源码:

type Map struct {
    mu     sync.Mutex       // 保护 dirty 操作
    read   atomic.Value     // 只读缓存(atomic 访问)
    dirty  map[interface{}]*entry  // 写入缓冲区
    misses int              // read 未命中计数器
}

type entry struct {
    p unsafe.Pointer  // 可能的状态:nil, expunged, 有效指针
}

Go 语言标准库中的 sync.map 专为以下场景优化:

  • 读多写少(98% 读操作)
  • 动态键空间(频繁创建/删除键)
  • 需要保证并发安全

性能对比测试: 测试场景为4核CPU环境下并发读写

实现方式100万次读/写 (ns/op)内存占用 (MB)
map+sync.RWMutex42032
sync.Map8528

实现有序的map

在Go语言中,标准库的map是无序的,但可以通过组合数据结构实现有序映射。以下是几种常见实现方案,根据需求选择最适合的方式:

方案一:维护插入顺序(链表法)
package main

import"fmt"

type OrderedMap struct {
    items map[interface{}]interface{}
    order []interface{}
}

func NewOrderedMap() *OrderedMap {
    return &OrderedMap{
        items: make(map[interface{}]interface{}),
        order: make([]interface{}, 0),
    }
}

func (m *OrderedMap) Set(key, value interface{}) {
    if _, exists := m.items[key]; !exists {
        m.order = append(m.order, key)
    }
    m.items[key] = value
}

func (m *OrderedMap) Get(key interface{}) (interface{}, bool) {
    val, exists := m.items[key]
    return val, exists
}

func (m *OrderedMap) Delete(key interface{}) {
    delete(m.items, key)
    // 重建顺序切片(简单实现,实际可用更高效方式)
    newOrder := make([]interface{}, 0, len(m.order)-1)
    for _, k := range m.order {
        if k != key {
            newOrder = append(newOrder, k)
        }
    }
    m.order = newOrder
}

func (m *OrderedMap) Iterate() {
    for _, key := range m.order {
        fmt.Printf("%v: %v\n", key, m.items[key])
    }
}

方案二:排序映射(使用sort包)
package main

import (
    "fmt"
    "sort"
)

type SortedMap struct {
    keys  []int
    items map[int]string
}

func NewSortedMap() *SortedMap {
    return &SortedMap{
        keys:  make([]int, 0),
        items: make(map[int]string),
    }
}

func (m *SortedMap) Set(key int, value string) {
    if _, exists := m.items[key]; !exists {
        m.keys = append(m.keys, key)
        sort.Ints(m.keys) // 保持有序
    }
    m.items[key] = value
}

func (m *SortedMap) Get(key int) (string, bool) {
    val, exists := m.items[key]
    return val, exists
}

func (m *SortedMap) Iterate() {
    for _, key := range m.keys {
        fmt.Printf("%d: %s\n", key, m.items[key])
    }
}

方案三:使用第三方库(推荐)
import "github.com/emirpasic/gods/maps/treemap"

func main() {
    // 自然排序
    m := treemap.NewWithIntComparator()
    m.Put(1, "one")
    m.Put(3, "three")
    m.Put(2, "two")

    // 迭代器
    it := m.Iterator()
    for it.Next() {
        fmt.Printf("%d: %s\n", it.Key(), it.Value())
    }

    // 反向迭代
    rit := m.ReverseIterator()
    for rit.Next() {
        fmt.Printf("%d: %s\n", rit.Key(), rit.Value())
    }
}

本篇结束~

欢迎关注我

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2374155.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

需求分析阶段测试工程师主要做哪些事情

在软件测试需求分析阶段,主要围绕确定测试范围、明确测试目标、细化测试内容等方面开展工作,为后续测试计划的制定、测试用例的设计以及测试执行提供清晰、准确的依据。以下是该阶段具体要做的事情: 1. 需求收集与整理 收集需求文档&#x…

项目模拟实现消息队列第二天

消息应答的模式 1.自动应答: 消费者把这个消息取走了,就算是应答了(相当于没有应答) 2.手动应答: basicAck方法属于手动应答(消费者需要主动调用这个api进行应答) 小结 1.需要实现生产者,broker server,消费者这三个部分的 2.针对生产者和消费…

5.Redission

5.1 前文锁问题 基于 setnx 实现的分布式锁存在下面的问题: 重入问题:重入问题是指 获得锁的线程可以再次进入到相同的锁的代码块中,可重入锁的意义在于防止死锁,比如 HashTable 这样的代码中,他的方法都是使用 sync…

dify 部署后docker 配置文件修改

1:修改 复制 ./dify/docker/.env.example ./dify/docker/.env 添加一下内容 # 启用自定义模型 CUSTOM_MODEL_ENABLEDtrue# 将OLLAMA_API_BASE_URL 改为宿主机的物理ip OLLAMA_API_BASE_URLhttp://192.168.72.8:11434# vllm 的 OPENAI的兼容 API 地址 CUSTOM_MODE…

数据结构——排序(万字解说)初阶数据结构完

目录 1.排序 2.实现常见的排序算法 2.1 直接插入排序 ​编辑 2.2 希尔排序 2.3 直接选择排序 2.4 堆排序 2.5 冒泡排序 2.6 快速排序 2.6.1 递归版本 2.6.1.1 hoare版本 2.6.1.2 挖坑法 2.6.1.3 lomuto前后指针 2.6.1.4 时间复杂度 2.6.2 非递归版本 2.7 归并排序…

快速入门深度学习系列(3)----神经网络

本文只针对图进行解释重要内容 这就是入门所需要掌握的大部分内容 对于不懂的名词或概念 你可以及时去查 对于层数 标在上面 对于该层的第几个元素 标在下面 输入层算作第0层 对于第一层的w b 参数 维度如下w:4*3 b:4*1 这个叫做神经元 比如对于第一层的神经元 这里说的很…

在线工具源码_字典查询_汉语词典_成语查询_择吉黄历等255个工具数百万数据 养站神器,安装教程

在线工具源码_字典查询_汉语词典_成语查询_择吉黄历等255个工具数百万数据 养站神器,安装教程 资源宝分享:https://www.httple.net/154301.html 一次性打包涵盖200个常用工具!无论是日常的图片处理、文件格式转换,还是实用的时间…

Linux 阻塞和非阻塞 I/O 简明指南

目录 声明 1. 阻塞和非阻塞简介 2. 等待队列 2.1 等待队列头 2.2 等待队列项 2.3 将队列项添加/移除等待队列头 2.4 等待唤醒 2.5 等待事件 3. 轮询 3.1 select函数 3.2 poll函数 3.3 epoll函数 4. Linux 驱动下的 poll 操作函数 声明 本博客所记录的关于正点原子…

Java开发经验——阿里巴巴编码规范经验总结2

摘要 这篇文章是关于Java开发中阿里巴巴编码规范的经验总结。它强调了避免使用Apache BeanUtils进行属性复制,因为它效率低下且类型转换不安全。推荐使用Spring BeanUtils、Hutool BeanUtil、MapStruct或手动赋值等替代方案。文章还指出不应在视图模板中加入复杂逻…

机器人手臂“听不懂“指令?Ethercat转PROFINET网关妙解通信僵局

机器人手臂"听不懂"指令?Ethercat转PROFINET网关妙解产线通信僵局 协作机器人(如KUKA iiWA)使用EtherCAT控制,与Profinet主站(如西门子840D CNC)同步动作。 客户反馈:基于Profinet…

深度学习 CNN

CNN 简介 什么是 CNN? 卷积神经网络(Convolutional Neural Network)是专为处理网格数据(如图像)设计的神经网络。核心组件: 卷积层 :提取局部特征(如边缘、纹理)通过卷…

MySQL索引原理以及SQL优化(二)

目录 1. 索引与约束 1.1 索引是什么 1.2 索引的目的 1.3 索引分类 1.3.1 数据结构 1.3.2 物理存储 1.3.3 列属性 1.3.4 列的个数 1.4 主键的选择 1.5 索引使用场景 1.6 索引的底层实现 1.6.1 索引存储 1.6.2 页 1.6.3 B 树 1.6.4 B 树层高问题 1.6.5 自增 id 1.7 innod…

MATLAB中矩阵和数组的区别

文章目录 前言环境配置1. 数据结构本质2. 运算规则(1)基本运算(2)特殊运算 3. 函数与操作4. 高维支持5. 创建方式 前言 在 MATLAB 中,矩阵(Matrix) 和 数组(Array) 的概…

Desfire Ev1\Ev2\Ev3卡DES\3K3DES\AES加解密读写C#示例源码

本示例使用的发卡器:https://item.taobao.com/item.htm?spma21dvs.23580594.0.0.1d292c1bYhsS9c&ftt&id917152255720 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using S…

MySQL核心内容【完结】

MySQL核心内容 文章目录 MySQL核心内容1.MySQL核心内容目录2.MySQL知识面扩展3.MySQL安装4.MySQL配置目录介绍Mysql配置远程ip连接 5.MySQL基础1.MySQL数据类型1.数值类型2.字符串类型3.日期和时间类型4.enum和set 2.MySQL运算符1.算数运算符2.逻辑运算符3.比较运算符 3.MySQL完…

C++类和对象进阶 —— 与数据结构的结合

🎁个人主页:工藤新一 🔍系列专栏:C面向对象(类和对象篇) 🌟心中的天空之城,终会照亮我前方的路 🎉欢迎大家点赞👍评论📝收藏⭐文章 文章目录 […

Django之账号登录及权限管理

账号登录及权限管理 目录 1.登录功能 2.退出登录 3.权限管理 4.代码展示合集 这篇文章, 会讲到如何实现账号登录。账号就是我们上一篇文章写的账号管理功能, 就使用那里面已经创建好的账号。这一次登录, 我们分为三种角色, 分别是员工, 领导, 管理员。不同的角色, 登录进去…

EXCEL中嵌入其他表格等文件

在EXCEL中嵌入其他表格 先放链接:https://jingyan.baidu.com/article/295430f11708c34d7e00509a.html 步骤如下: 1、打开一个需要嵌入新表格的excel表。 2、切换至“插入”菜单中,单击选择“对象”。 3、如下图所示,会弹出“对象…

21. LangChain金融领域:合同审查与风险预警自动化

引言:当AI成为24小时不眠的法律顾问 2025年某商业银行的智能合同系统,将百万级合同审查时间从平均3周缩短至9分钟,风险条款识别准确率达98.7%。本文将基于LangChain的金融法律框架,详解如何构建合规、精准、可追溯的智能风控体系…

Springboot使用事件流调用大模型接口

什么是事件流 事件流(Event Stream) 是一种处理和传递事件的方式,通常用于系统中的异步消息传递或实时数据流。在事件驱动架构(Event-Driven Architecture)中,事件流扮演着至关重要的角色。 事件流的概念…