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

Golang | 每日一练 (3)

💢欢迎来到张胤尘的技术站
💥技术如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌💥

文章目录

  • Golang | 每日一练 (3)
    • 题目
    • 参考答案
      • `map` 实现原理
        • `hmap`
        • `bmap`
        • 数据存储模型
        • 键值底层访问
          • 竞态检测
          • `Sanitizer` 检测
          • 空检查
          • 并发写检查
          • 哈希值计算
          • 桶定位
          • 扩容情况处理
          • 桶内查找
      • 安全并发访问 `map`
        • 使用 `sync.Mutex` 或者 `sync.RWMutex`
        • 并发安全的 `sync.Map`

Golang | 每日一练 (3)

题目

golang 中的 map 是如何实现的?如何安全地并发访问 map

参考答案

map 实现原理

golang 中,map 是一种灵活且高效的数据结构,底层是基于哈希表实现,键值对存储数据。

map 的内部由两个核心结构体组成:hmapbmap

hmap

hmapgolangmap 的底层核心数据结构之一,它封装了哈希表的所有关键信息。源码如下所示:

源码位置:src/runtime/map.go

// A header for a Go map.
type hmap struct {// Note: the format of the hmap is also encoded in cmd/compile/internal/reflectdata/reflect.go.// Make sure this stays in sync with the compiler's definition.count     int // # live cells == size of map.  Must be first (used by len() builtin)flags     uint8B         uint8  // log_2 of # of buckets (can hold up to loadFactor * 2^B items)noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for detailshash0     uint32 // hash seedbuckets    unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growingnevacuate  uintptr        // progress counter for evacuation (buckets less than this have been evacuated)extra *mapextra // optional fields
}
  • count:表示当前 map 中存储的键值对数量,len() 直接访问它。
  • flags:用于存储一些标志位,例如是否正在扩容、是否需要清理等。
  • B:表示桶的数量为 2^B。例如,如果 B = 3,则桶的数量为 2^3 = 8B 的值决定了 buckets 数组的大小。
  • noverflow:表示溢出桶的数量。当一个桶满了(最多存储 8 对键值对),会创建一个溢出桶,并通过链表连接。
  • hash0:哈希种子,用于计算键的哈希值。通过哈希种子可以避免哈希冲突,增加哈希值的随机性。
  • buckets:指向底层桶数组的指针,桶数组的大小为 2^B,每个桶是一个 bmap 结构体。
  • oldbuckets:在扩容时,旧的桶数组会存储在这里。新的桶数组大小是旧数组的两倍。扩容完成后,oldbuckets 会被释放。
  • nevacuate:用于记录扩容进度的计数器。表示已经迁移完成的桶数量。
  • extra:存储一些可选字段。
bmap

bmap 是存储键值对的“桶”,每个桶可以存储最多 8 对键值对。源码如下所示:

源码位置:src/runtime/map.go

// A bucket for a Go map.
type bmap struct {// tophash generally contains the top byte of the hash value// for each key in this bucket. If tophash[0] < minTopHash,// tophash[0] is a bucket evacuation state instead.tophash [abi.MapBucketCount]uint8// Followed by bucketCnt keys and then bucketCnt elems.// NOTE: packing all the keys together and then all the elems together makes the// code a bit more complicated than alternating key/elem/key/elem/... but it allows// us to eliminate padding which would be needed for, e.g., map[int64]int8.// Followed by an overflow pointer.
}
  • tophashabi.MapBucketCount 是一个常量,值为 8。存储每个键的哈希值的最高字节(top byte)。特殊情况:如果 tophash[0] < minTopHash,则表示该桶处于迁移状态,而不是存储键的哈希值。
// Maximum number of key/elem pairs a bucket can hold.
MapBucketCountBits = 3 // log2 of number of elements in a bucket.
MapBucketCount     = 1 << MapBucketCountBits
minTopHash     = 5 // minimum tophash for a normal filled cell.
  • tophash 之后,bmap 会依次存储键和值。键和值的存储方式是连续的:先存储所有键(bucketCnt 个键),然后存储所有值(bucketCnt 个值)。这种设计可以减少内存对齐时的填充,从而节省内存。例如,在 map[int64]int8 的情况下,如果键和值交替存储,可能会因为对齐问题浪费内存。

  • 最后在每个 bmap 的末尾包含一个指向下一个溢出桶的指针(overflow)。当一个桶满了(最多存储 8 对键值对)时,会通过链表的方式创建一个溢出桶,用于存储额外的键值对。

数据存储模型

例如:在64位平台上有一个 map[int]string,键的大小为 8 字节(int64),值的大小为 16 字节(指向字符串数据的指针(8 字节)和字符串的长度(8 字节))。一个 bmap 的内存布局如下所示:

在这里插入图片描述

键值底层访问

map 数据存储模型可知,因为键和值的存储是动态的,访问键和值时就需要通过指针偏移来实现。源码内容如下所示:

源码位置:src/runtime/map.go

// mapaccess1 returns a pointer to h[key].  Never returns nil, instead
// it will return a reference to the zero object for the elem type if
// the key is not in the map.
// NOTE: The returned pointer may keep the whole map live, so don't
// hold onto it for very long.
func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {// ...
}
  • t *maptypemap 的类型信息,例如键的类型、值的类型、哈希函数等。
  • h *hmapmap 的底层结构,包含哈希表的元数据(如桶数组、键值对数量等)。
  • key unsafe.Pointer:查找目标键的指针。
  • 返回值:返回指向值的指针。如果键不存在,则返回值类型的零值的指针。

对于 mapaccess1 源码的流程进行了如下步骤的拆解:

  • 竞态检测
  • Sanitizer 检测
  • 空检查
  • 并发写检查
  • 哈希值计算
  • 桶定位
  • 扩容情况处理
  • 桶查找

下面针对每一步骤进行详细说明。

竞态检测

如果启用了竞态检测,记录当前操作的上下文,以便在发生竞态时能够追踪。

if raceenabled && h != nil {callerpc := getcallerpc()pc := abi.FuncPCABIInternal(mapaccess1)racereadpc(unsafe.Pointer(h), callerpc, pc)raceReadObjectPC(t.Key, key, callerpc, pc)
}
Sanitizer 检测

msanread 会标记对 key 的读取操作,确保该内存区域已经被正确初始化。防止程序读取未初始化的内存,从而避免潜在的未定义行为。

asanread 会检查对 key 的读取操作是否安全,例如是否越界或是否访问了已释放的内存。

if msanenabled && h != nil {msanread(key, t.Key.Size_)
}
if asanenabled && h != nil {asanread(key, t.Key.Size_)
}
空检查

如果 map 为空,直接返回值类型的零值。

if h == nil || h.count == 0 {if err := mapKeyError(t, key); err != nil {panic(err) // see issue 23734}return unsafe.Pointer(&zeroVal[0])
}
并发写检查

如果 map 正在被写入(hashWriting 标志被设置),抛出并发读写错误,这一点也表明 map 并不支持并发安全。

if h.flags&hashWriting != 0 {fatal("concurrent map read and map write")
}
哈希值计算

使用键的哈希函数计算哈希值,其中 h.hash0 是哈希种子,用于避免哈希冲突。

hash := t.Hasher(key, uintptr(h.hash0))
桶定位

代码中使用哈希值的低 B 位(bucketMask(h.B))定位到初始桶。其中 BucketSize 是每个桶的大小(包括键和值的存储)。

m := bucketMask(h.B)
b := (*bmap)(add(h.buckets, (hash&m)*uintptr(t.BucketSize)))
扩容情况处理

如果当前真正在扩容,那么检查旧的桶数组 oldbuckets。如果旧桶尚未迁移完成(!evacuated(oldb)),使用旧桶进行查找。

if c := h.oldbuckets; c != nil {if !h.sameSizeGrow() {// There used to be half as many buckets; mask down one more power of two.// 如果扩容前的桶数量是当前的一半,进一步掩码哈希值m >>= 1}oldb := (*bmap)(add(c, (hash&m)*uintptr(t.BucketSize)))if !evacuated(oldb) {b = oldb}
}
桶内查找
// 获取键的哈希值的最高字节
top := tophash(hash)
bucketloop:// 遍历当前桶及其溢出桶for ; b != nil; b = b.overflow(t) {// 遍历桶内的所有键值对for i := uintptr(0); i < abi.MapBucketCount; i++ {// 检查当前个键的哈希值最高字节是否匹配,如果不相等,说明当前槽位的键与目标键不匹配if b.tophash[i] != top {// 如果遇到空槽(emptyRest)跳出桶循环,因为后续槽位都是空的if b.tophash[i] == emptyRest {break bucketloop}// 不匹配则跳过当前槽位continue}// 计算第 i 个键的地址k := add(unsafe.Pointer(b), dataOffset+i*uintptr(t.KeySize))// 如果键是指针类型,解引用键的指针if t.IndirectKey() {k = *((*unsafe.Pointer)(k))}// 比较传入的键和当前键是否相等if t.Key.Equal(key, k) {// 计算第 i 个值的地址e := add(unsafe.Pointer(b), dataOffset+abi.MapBucketCount*uintptr(t.KeySize)+i*uintptr(t.ValueSize))// 如果值是指针类型,解引用值的指针if t.IndirectElem() {e = *((*unsafe.Pointer)(e))}// 返回值的指针return e}}}// 如果未找到,则返回值类型的零值指针return unsafe.Pointer(&zeroVal[0])

根据上一小结中的 bmap 数据存储模型可知,桶内查找中最为重要的就是键的偏移量计算和值的偏移量计算,如下所示:

k := add(unsafe.Pointer(b), dataOffset+i*uintptr(t.KeySize))

其中,dataOffsettophash 数组之后的偏移量,i * uintptr(t.KeySize) 是计算得第 i 个键的偏移量。

e := add(unsafe.Pointer(b), dataOffset+abi.MapBucketCount*uintptr(t.KeySize)+i*uintptr(t.ValueSize))

其中,dataOffset + abi.MapBucketCount*uintptr(t.KeySize) 是值的起始偏移量(所有键之后);i * uintptr(t.ValueSize) 是第 i 个值的偏移量。

安全并发访问 map

由前一节可知, map 并非并发安全的,直接在多个 goroutine 中并发的修改同一个 map 时,会导致数据竞争和不可预测的行为。

为了安全地并发访问 map,可以采用以下几种方法:

使用 sync.Mutex 或者 sync.RWMutex

代码如下所示:

package mainimport ("fmt""sync"
)func main() {var mu sync.RWMutexmyMap := make(map[int]int)var wg sync.WaitGroupfor i := 0; i < 100; i++ { // 启动100个协程wg.Add(1)go func(val int) {defer wg.Done()mu.Lock() // 加写锁myMap[val] = val * 2mu.Unlock() // 释放写锁}(i)}wg.Wait() // 等待协程结束mu.RLock() // 加读锁fmt.Println("Map content:", myMap)mu.RUnlock() // 释放读锁
}

在读取时使用 mu.RLock()mu.RUnlock(),在写入时使用 mu.Lock()mu.Unlock()。另外 sync.RWMutex 允许多个读操作并发执行,但写操作互斥。

并发安全的 sync.Map

代码如下所示:

package mainimport ("fmt""sync"
)func main() {var myMap sync.Mapvar wg sync.WaitGroupfor i := 0; i < 10; i++ {wg.Add(1)go func(val int) {defer wg.Done()myMap.Store(val, val*2) // 存储键值对}(i)}wg.Wait()// Key: 0, Value: 0// Key: 2, Value: 4// Key: 3, Value: 6// Key: 7, Value: 14// Key: 8, Value: 16// Key: 9, Value: 18// Key: 1, Value: 2// Key: 4, Value: 8// Key: 5, Value: 10// Key: 6, Value: 12myMap.Range(func(key, value interface{}) bool { // 遍历所有键值对fmt.Printf("Key: %v, Value: %v\n", key, value)return true})
}

关于 golang 中的锁和并发编程相关的知识点,这里不在赘述,请后续关注文章 《Golang 并发编程》。

关于 golangmap 更多的知识点,请后续关注文章 《Golang 映射》。

🌺🌺🌺撒花!

如果本文对你有帮助,就点关注或者留个👍
如果您有任何技术问题或者需要更多其他的内容,请随时向我提问。

在这里插入图片描述

相关文章:

Golang | 每日一练 (3)

&#x1f4a2;欢迎来到张胤尘的技术站 &#x1f4a5;技术如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 Golang | 每日一练 (3)题目参考答案map 实现原理hmapb…...

Java+SpringBoot+Vue+数据可视化的综合健身管理平台(程序+论文+讲解+安装+调试+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统介绍 在当今社会&#xff0c;随着人们生活水平的不断提高和健康意识的日益增强&#xff0c;健…...

深入解析Textual库:打造现代化的终端用户界面(TUI)

深入解析Textual库&#xff1a;打造现代化的终端用户界面&#xff08;TUI&#xff09; 在终端应用程序的世界里&#xff0c;过去的交互方式通常是简单的命令行输入和文本输出。然而&#xff0c;随着开发者对更高可用性和更友好界面的追求&#xff0c;现代终端用户界面&#xf…...

基于ffmpeg+openGL ES实现的视频编辑工具-opengl相关逻辑(五)

在我们的项目中,OpenGL ES 扮演着至关重要的角色,其主要功能是获取图像数据,经过一系列修饰后将处理结果展示到屏幕上,以此实现各种丰富多样的视觉效果。为了让大家更好地理解后续知识,本文将详细介绍 OpenGL 相关代码。需要注意的是,当前方案将对 OpenGL 的所有操作都集…...

加班限制了进步

今天周六&#xff0c;大家都在加班吗&#xff1f; 做个统计。 最近面试了很多硬件工程师&#xff0c;还没有找到如意的。 这些面试者都很会解决问题&#xff0c;但是不会闭环问题。 EMC不过&#xff0c;加个磁环就过了。为什么加磁环就过了&#xff0c;底层原理不清楚。 改…...

容器化部署tomcat

容器化部署tomcat 需求在docker容器中部署tomcat,并通过外部机器访问tomcat部署的项目 容器化部署要先装好docker容器(docker安装配置) 实现步骤&#xff1a; 拉取tomcat docker pull tomcat用于列出本地Docker主机上存储的所有镜像 docker images在root目录里面创建tomc…...

【HeadFirst系列之HeadFirst设计模式】第7天之命令模式:封装请求,轻松实现解耦!

命令模式&#xff1a;封装请求&#xff0c;轻松实现解耦&#xff01; 大家好&#xff01;今天我们来聊聊设计模式中的命令模式&#xff08;Command Pattern&#xff09;。如果你曾经需要将请求封装成对象&#xff0c;或者希望实现请求的撤销、重做等功能&#xff0c;那么命令模…...

尚硅谷爬虫note009

一、jsonpath 1.安装 pip install jsonpath 2.使用 只能解析本地文件 .json文件 {"store": {"book": [{"category": "reference","author": "Nigel Rees","title": "Sayings of the Century&qu…...

C语言(11)------------->while循环

一、if与while的区别 在C语言中&#xff0c;有三大结构&#xff0c;分别是顺序、选择和循环。在前面的博客文章中&#xff0c;我们解释了if语句的用法&#xff0c;可以参考&#xff1a;C语言&#xff08;7&#xff09;------------&#xff1e;if语句-CSDN博客 从文章中&…...

Unity 全局屏幕点击特效

思路&#xff1a; 1、生成一个点击特效实例&#xff0c;每点击屏幕&#xff0c;就调整特效实例的位置并控制特效的显隐状态即可。 2、需要注意要保证在编辑器开发时或手机上运行时都要显示点击效果。 方案一 &#xff08;推荐&#xff09; using UnityEngine; using UnityEn…...

【数据结构初阶第十二节】设计循环队列

云边有个稻草人-CSDN博客 必须有为成功付出代价的决心&#xff0c;然后想办法付出这个代价。 还有最后一道关于队列的习题&#xff0c;这题有点难&#xff0c;准备好迎接挑战吧&#xff01; 目录 1.【题目】 2.实现循环队列推荐用数组&#xff0c;Why? 3.Q1&#xff1a;如…...

【小白学HTML5】盒模型(一文讲清margin、padding)_第三讲

根据第一讲的内容&#xff0c;我们知道margin是外边距、padding是内边距&#xff0c;那么内外边距该怎么设置呢&#xff1f; 1、margin&#xff1a;外边距 第一种情况&#xff1a;比如设置外边距为上10px、右20px、下30px、左40px 外边距可以分别设置为&#xff1a;margin-t…...

PLC数据采集网关(三格电子)

产品概述 PLC转Modbus网关型号SG-PLC-Private&#xff08;PLC私有协议网关&#xff09;&#xff0c;是三格电子推出的工业级网关&#xff08;以下简称网关&#xff09;&#xff0c;主要用于在不需要对PLC编程的情况下将PLC数据映射到Modbus TCP(映射的方式符合PLC工程师使用习惯…...

基于图扑 HT 可视化实现智慧地下采矿可视化

在前端开发领域&#xff0c;不断涌现的新技术为各行业带来了创新变革的可能。今天&#xff0c;让我们聚焦于图扑软件自研的 HT for Web 产品&#xff0c;看看它如何在前端 2D、3D 渲染方面发力&#xff0c;为智慧地下采矿可视化打造令人惊叹的解决方案&#xff0c;为开发者开启…...

【网络】高级IO(2)

或者在某些情况下&#xff0c;它可能是&#xff1a; typedef unsigned int nfds_t; 前言 由于select函数有下面几个特别明显的缺点&#xff0c;就推演出了改进版本——poll函数 比如select监视的fd是有上限的&#xff0c;我的云服务器内核版本下最大上限是1024个fd&#xf…...

论文解读 | AAAI'25 Cobra:多模态扩展的大型语言模型,以实现高效推理

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 点击 阅读原文 观看作者讲解回放&#xff01; 个人信息 作者&#xff1a;赵晗&#xff0c;浙江大学-西湖大学联合培养博士生 内容简介 近年来&#xff0c;在各个领域应用多模态大语言模型&#xff08;MLLMs&…...

区块链共识机制详解

区块链共识机制详解 &#x1f91d; 1. 什么是共识机制&#xff1f; 共识机制是区块链网络中&#xff0c;所有节点就某个状态&#xff08;如交易的有效性&#xff09;达成一致的规则和过程。它解决了在去中心化网络中如何确保数据一致性的问题。 2. 主流共识机制 2.1 工作量证…...

Unity游戏制作中的C#基础(1)界面操作基础

1.脚本有关注意事项 &#xff08;1&#xff09;.进入项目之后&#xff0c;一般创建一个文件夹Scripts用来存放c#脚本&#xff1b; &#xff08;2&#xff09;.在Scripts中创建脚本&#xff0c;双击脚本&#xff0c;进入VS编辑器&#xff0c;有如下结构&#xff1a; start&#…...

python学习笔记,python处理 Excel、Word、PPT 以及邮件自动化办公

文章目录 前言一、环境搭建1. 下载 Python2. 安装 Python 二、处理 Excel 文件&#xff08;openpyxl库&#xff09;三、 处理 Word 文件&#xff08;python-docx库&#xff09;四、 处理 PPT 文件&#xff08;python-pptx库&#xff09;五、 自动发送邮件&#xff08;smtplib和…...

欢乐力扣:同构字符串

文章目录 1、题目描述2、 代码 1、题目描述 同构字符串。给定两个字符串 s 和 t &#xff0c;判断它们是否是同构的。如果 s 中的字符可以按某种映射关系替换得到 t &#xff0c;那么这两个字符串是同构的。  每个出现的字符都应当映射到另一个字符&#xff0c;同时不改变字符…...

近10年气象分析(深度学习)

这是一个气象数据分析程序&#xff0c;主要用于分析和可视化气象数据。以下是该文件的主要功能&#xff1a; 1. 数据加载 在线数据&#xff1a;尝试从 GitHub 加载气象数据。 示例数据&#xff1a;如果无法加载在线数据&#xff0c;程序会自动生成示例数据。 2. 数据分析 …...

win11系统无法打开软件_组策略无法打开_gpedit.msc不生效_为了对电脑进行保护,已经阻止此应用---Windows工作笔记057

碰到这个问题挺麻烦的,要用的软件打不开了. 其实解决方法就是去组策略中修改一个策略就可以了,但是: 先来说: 而且,使用cmd输入的gpedit.msc也打不开了. 这个怎么解决? @echo off pushd "%~dp0"dir /b C:\Windows\servicing\Packages\Microsoft-Windows-GroupPo…...

【JAVA】封装多线程实现

系列文章目录 java知识点 文章目录 系列文章目录&#x1f449;前言&#x1f449;一、封装的目标&#x1f449;二、常见的封装方式及原理&#x1f449;壁纸分享&#x1f449;总结 &#x1f449;前言 在 Java 中&#xff0c;封装多线程的原理主要围绕着将多线程相关的操作和逻辑…...

长短期记忆网络:从理论到创新应用的深度剖析

一、引言 1.1 研究背景 深度学习在人工智能领域的发展可谓突飞猛进&#xff0c;而长短期记忆网络&#xff08;LSTM&#xff09;在其中占据着至关重要的地位。随着数据量的不断增长和对时序数据处理需求的增加&#xff0c;传统的神经网络在处理长序列数据时面临着梯度消失和梯…...

过程监督(Process Supervision)融入到 GRPO (Group Relative Policy Optimization)

下面演示如何把“过程监督&#xff08;Process Supervision&#xff09;”的思想融入到 GRPO (Group Relative Policy Optimization) 中&#xff0c;从而对每个输出的中间步骤逐一打分、计算相对优势。本文的示例代码与 grpo_train.py &#xff08;来源见下文&#xff09;类似&…...

ES6中Object.defineProperty 的详细用法和使用场景以及例子

ES6 Object.defineProperty() 用法总结 Object.defineProperty() 是 ES5 引入的一个方法&#xff0c;ES6 继续强化了该方法的使用&#xff0c;它允许我们为对象的属性定义或修改 属性描述符。它能够控制对象属性的行为&#xff0c;如读写权限、可枚举性和可配置性。 1. Objec…...

【服务器与本地互传文件】远端服务器的Linux系统 和 本地Windows系统 互传文件

rz 命令&#xff1a;本地上传到远端 rz 命令&#xff1a;用于从本地主机上传文件到远程服务器 rz 是一个用于在 Linux 系统中通过 串口 或 SSH 上传文件的命令&#xff0c;它实际上是 lrzsz 工具包中的一个命令。rz 命令可以调用一个图形化的上传窗口&#xff0c;方便用户从本…...

NVIDIA A100 SXM4与NVIDIA A100 PCIe版本区别深度对比:架构、性能与场景解析

NVIDIA A100 SXM4与PCIe版本深度对比&#xff1a;架构、性能与场景解析 作为NVIDIA Ampere架构的旗舰级数据中心GPU&#xff0c;A100系列凭借强大的计算能力和显存带宽&#xff0c;已成为人工智能训练、高性能计算&#xff08;HPC&#xff09;等领域的核心硬件。然而&#xff…...

RAG基本原理

1.RAG全称是Retrieval-Augmented Generation Generation 的含义是 基于用户的输入&#xff0c;生成具有上下文含义的一段文字。 Query 比如说 太阳系中&#xff0c;哪个行星拥有的卫星数目最多&#xff1f; 回答Answer 木星&#xff0c;木星目前有79个卫星 这样的回答存在两个…...

WPS接入deepseek-OfficeAI助手插件下载

功能简介 OfficeAI 助手 是一款免费的智能AI办公工具软件&#xff0c;专为 Microsoft Office 和 WPS 用户打造。 无论你是在寻找如何输入“打勾&#xff08;√&#xff09;符号”的方法&#xff0c;还是想知道“怎么在插入表格前添加文字”&#xff0c;或者“该用哪个公式”&a…...

【微中子代理踩坑-前端node-sass安装失败】

微中子代理踩坑-前端node-sass安装失败-windows 1.npm版本2.python2.73.安装Visual Studio 1.npm版本 当前使用node版本13.12.0 2.python2.7 安装python2.7.9并配置环境变量 3.安装Visual Studio 安装Visual Studio 我是直接勾选了3个windows的sdk,然后就好了 最后 npm in…...

在群晖上使用Docker安装思源笔记

​​ 最近一段时间&#xff0c;docker的镜像地址都失效了&#xff0c;在群晖系统中&#xff0c;无论是早期版本的docker&#xff0c;还是最新版本中的Container Manager&#xff0c;注册表中都无法链接到docker的镜像&#xff0c;于是&#xff0c;就花了点时间查找资料&#x…...

后端之路——阿里云OSS云存储

一、何为阿里云OSS 全名叫“阿里云对象存储OSS”&#xff0c;就是云存储&#xff0c;前端发文件到服务器&#xff0c;服务器不用再存到本地磁盘&#xff0c;可以直接传给“阿里云OSS”&#xff0c;存在网上。 二、怎么用 大体逻辑&#xff1a; 细分的话就是&#xff1a; 1、准…...

华为guass在dbever和springboot配置操作

下面记录华为guass在dbever和springboot配置操作&#xff0c;以备忘。 1、安装dbeaver-ce-23.2.0-x86_64-setup.exe和驱动程序 Download | DBeaver Community 2、配置高斯数据库驱动 3、新建数据库连接 4、操作指引 opengauss官方文档 https://docs-opengauss.osinfra.cn/zh…...

【STM32学习】标准库实现STM32 ADC采集1路、2路、多路

目录 ADC采集 ADC配置步骤 STM32F103C8T6的ADC 输入通道 ​编辑 1路ADC&#xff08;A4 ADC 通道4&#xff09; 1路ADC源码代码链接&#xff1a; 2路ADC&#xff08;A4 ADC 通道4、A5 ADC 通道5&#xff09;基于DMA实现 多路ADC实现采集 ADC采集 ADC配置步骤 使能GPIO…...

常用网络工具分析(ping,tcpdump等)

写在前面 本文看下常用网络工具。 1&#xff1a;ping 1.1&#xff1a;用途 用于检验网络的连通性。 1.2&#xff1a;实战 在Linux环境中执行&#xff1a;ping www.sina.com.cn&#xff1a; [rootlocalhost ~]# ping www.sina.com.cn PING spool.grid.sinaedge.com (111.…...

计算机视觉:主流数据集整理

第一章&#xff1a;计算机视觉中图像的基础认知 第二章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(一) 第三章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(二) 第四章&#xff1a;搭建一个经典的LeNet5神经网络(附代码) 第五章&#xff1…...

1.1 go环境搭建及基本使用

golang下载地址&#xff1a; Download and install - The Go Programming Language (google.cn) 验证安装是否成功&#xff1a; go version 查看go环境 go env 注意&#xff1a;Go1.11版本之后无需手动配置环境变量,使用go mod 管理项目&#xff0c;也不需要把项目放到GO…...

《深入理解JVM》实战笔记(一):内存区域、对象布局与OOM排查指南

JVM发展史与Java内存区域深度解析 Java虚拟机&#xff08;JVM&#xff09;是Java编程语言的核心部分&#xff0c;它允许Java程序跨平台运行&#xff0c;提供了一个抽象层&#xff0c;使得Java代码能够在不同操作系统和硬件平台上运行。本文将从JVM的发展历程开始&#xff0c;深…...

《筑牢元宇宙根基:AI与区块链的安全信任密码》

在科技浪潮汹涌澎湃的当下&#xff0c;元宇宙已不再是科幻作品中的遥远构想&#xff0c;而是逐渐步入现实&#xff0c;成为人们热议与探索的前沿领域。从沉浸式的虚拟社交&#xff0c;到创新的数字经济模式&#xff0c;元宇宙的发展前景广阔&#xff0c;潜力无限。但要让元宇宙…...

Docker构建时,设定默认进入的工作目录的方法

在 Docker 中,你可以通过不同的方式来设定容器默认进入的目录,以下针对不同场景分别介绍具体方法: 1. 使用 Dockerfile 设定工作目录 如果你是通过构建镜像的方式来运行容器,那么可以在 Dockerfile 中使用 WORKDIR 指令来设置容器启动时的默认工作目录。以下是具体步骤:…...

Linux nohup

nohup 是 Linux 系统中一个非常实用的命令&#xff0c;它的英文全称是 “no hang up”&#xff08;不挂断&#xff09;&#xff0c;主要用于在用户退出登录或者终端会话关闭后&#xff0c;让指定的程序在后台持续运行&#xff0c;而不会受到 HUP&#xff08;hangup&#xff09;…...

【Linux探索学习】第二十七弹——信号(上):Linux 信号基础详解

Linux学习笔记&#xff1a; https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言&#xff1a; 前面我们已经将进程通信部分讲完了&#xff0c;现在我们来讲一个进程部分也非常重要的知识点——信号&#xff0c;信号也是进程间通信的一…...

ok113i平台——usb触摸屏驱动开发

在嵌入式Linux系统中&#xff0c;如果USB触摸屏能够检测到并且在手指移动时有数据&#xff0c;但点击无法触发&#xff0c;这可能是因为触摸屏驱动或配置的问题。以下是一些可能的解决方法&#xff1a; 1. 确认驱动支持 首先&#xff0c;确保您使用的触摸屏驱动程序完全支持您…...

【Bluedroid】AVRCP 连接源码分析(二)

接着上一篇【Bluedroid】AVRCP 连接源码分析(一)-CSDN博客,继续AVRCP连接的源码分析。 getcapabilities_cmd packages/modules/Bluetooth/system/btif/src/btif_rc.cc /***************************************************************************** Function …...

Jenkins 自动构建Job

1.创建Job 登录Jenkins,点击新建Item,创建项目 选择Pipeline&#xff0c;然后点击确定 接下来主要在Pipeline script中编写脚本 2.签出Git仓库 2.1配置Git账号 Manage Jenkins->Security->Credentials 在凭据界面&#xff0c;选择全局 添加凭据&#xff0c;添加Git用…...

现代企业软件测试人员需求与发展方向深度解析

引言 现代互联网软件行业是不断创新的引擎。应用程序越来越复杂&#xff0c;部署周期越来越短&#xff0c;用户期望越来越高&#xff0c;运营规模也越来越庞大。在这种动态环境中&#xff0c;软件测试人员的角色不再仅限于在发布前阶段“查找错误”。相反&#xff0c;测试人员…...

2.19学习(php文件后缀)

misc buu-后门查杀 下载附件&#xff0c;我们用火绒安全扫一下然后点击详情进入该文件所在文件夹&#xff0c;再用记事本打开该文件&#xff0c;搜索flag无果&#xff0c;再试试pass&#xff08;由题目中的密码联系到pass&#xff0c;password&#xff0c;key等&#xff09;&a…...

AI Agent实战:打造京东广告主的超级助手 | 京东零售技术实践

前言 自2022年末ChatGPT的问世&#xff0c;大语言模型&#xff08;LLM&#xff09;技术引发全球关注。在大模型技术落地的最佳实践中&#xff0c;智能体&#xff08;Agent&#xff09;架构显现出巨大潜力&#xff0c;成为业界的普遍共识&#xff0c;各大公司也纷纷启动Agent技…...

将Google文档导入WordPress:简单实用的几种方法

Google文档是内容创作者非常实用的写作工具。它支持在线编辑、多人协作&#xff0c;并能够自动保存内容。但当我们想把Google文档中的内容导入WordPress网站时&#xff0c;可能会遇到一些小麻烦&#xff0c;比如格式错乱、图片丢失等问题。本文将为大家介绍几种简单实用的方法&…...