GolangEP06:关于map-下

引子 上一篇文章中留下了两个问题没有解决 map 如何扩容 为什么原生的 map 线程不安全 其实这两个问题是有联系的,所以这篇文章来解决这两个问题。 map 的扩容机制 本节还是需要用到上一篇文章中的底层 hmap 结构 ...

七月 16, 2025 · 5 分钟 · LTX

GolangEP06:关于map-上

引子 在做两数之和时,操作 map 遇到了问题,可以看我下面的代码。 func twoSum(nums []int, target int) []int { sMap := make(map[int]int) for i, x := range nums { sMap[x] = i } var ans []int for i, y := range nums { // 如果另一个值在 map 中存在的话即下标大于等于 0;且要保证不能使用两次相同的元素 p := sMap[target-y] if p >= 0 && p != i { ans = append(ans, i) ans = append(ans, p) break } } return ans } 像极了一个 golang 新手的操作,特别是在判断 key 是否存在于哈希表中时,用值(下标)是否大于 0 来判断。(当然前面的哈希表的定义也有问题) ...

七月 16, 2025 · 3 分钟 · LTX

K3sEP08——make后会发生什么?从源码解析构建过程

引子 从 EP 07 中,我们可以看到已经有了成功的 riscv 移植工作,见此仓库. 发现其构建 riscv 采用了以下命令 # Build rm -rf bin dist build ARCH=riscv64 SKIP_IMAGE=true SKIP_VALIDATE=true SKIP_AIRGAP=true make # Split cd dist/artifacts gzip < k3s-riscv64 | split -b 20M - k3s-riscv64.gz. 在此 pull request 中他也提到了这一路上的适配工作过程:开始他是使用qemu模拟,之后在硬件上测试并适配我们之前提到过的各种镜像. ...

五月 13, 2025 · 4 分钟 · LTX

GolangEP05_Go中的并发

引子 之前的两篇文章关于context和channel,我们都从源码的角度去讨论了其各自的底层原理以及使用方法。 但是我并没有从宏观的角度上来阐述为什么我们需要并发?为什么要设计这两种结构来处理并发,本着做到"what-how-why"的态度,我们今天来深入讨论一下 Go 中的并发。 ...

五月 3, 2025 · 7 分钟 · LTX

GolangEP04_string底层原理及注意事项

引子 字符串操作在任何语言中的地位都十分重要,在上篇关于 Golang 中特殊的切片讲完之后,这一次我准备进入 Golang 中字符串的底层世界,包括引用总结自<100 Go Mistakes and How to Avoid Them (Teiva Harsanyi)> 书籍的注意事项。 ...

四月 25, 2025 · 10 分钟 · LTX

GolangEP03_slice底层原理及注意事项

引子 在做力扣的题目时,特别是遇到递归问题,需要传入参数,遇到切片的时候经常遇到需要克隆切片的情况,而遇到普通的int类型的时候却不需要。 显而易见,这是一个值传递还是引用传递的问题,所以今天我来总结一下 Golang 中切片的底层原理,为什么在递归中需要克隆它。 ...

四月 11, 2025 · 14 分钟 · LTX

GolangEP02_并发中的Channel

前言 让我们看看关于 chan 有哪些常见的操作。 创建channel ch1 := make(chan int) ch2 := make(chan int, 2) 底层实际上调用的是makechan方法 发送数据到channel ch <- 1 底层实际调用的是chansend1,而chansend1最终也是调用chansend,将block参数设置为true——当前发送操作是阻塞的 从channel中读取数据 i <- ch i, ok <- ch 底层实际调用的是chanrecv1和chanrecv2,最终都去调用了chanrecv。 源码 接下来我们进入源码中一探究竟。 hchan结构体 type hchan struct { qcount uint // total data in the queue dataqsiz uint // size of the circular queue buf unsafe.Pointer // points to an array of dataqsiz elements elemsize uint16 synctest bool // true if created in a synctest bubble closed uint32 timer *timer // timer feeding this chan elemtype *_type // element type sendx uint // send index recvx uint // receive index recvq waitq // list of recv waiters sendq waitq // list of send waiters // lock protects all fields in hchan, as well as several // fields in sudogs blocked on this channel. // // Do not change another G's status while holding this lock // (in particular, do not ready a G), as this can deadlock // with stack shrinking. lock mutex } qcount:通道中存储的数据元素总数 dataqsiz:环形队列大小 buf:执行环形队列的内存缓冲区,存放实际数据——环形缓存区域,本质上是一个带有头尾指针的固定长度的数组 sendx,recvx:发收操作的队列位置 recvq,sendq:等待队列 可以发现,hchan 使用环形队列表示缓冲区并且采用 lock 确保并发访问的安全性。 ...

十二月 5, 2024 · 8 分钟 · LTX

GolangEP01_并发之绕不过的context

引子 今天心血来潮,给自己梳理梳理golang中这个十分重要的东东——context,毕竟也是在面试中考察到,但是反问自己的时候却感觉一点也说不出来什么有价值的东西,所以今天我来一次刨根究底。 ...

十二月 1, 2024 · 10 分钟 · LTX
0:00 --:--