
lang
文章平均质量分 71
动态一时爽,重构火葬场
这个作者很懒,什么都没留下…
展开
-
GO goroutine状态流转
go池是所有拥有goroutine的地方,包括P的runnext、P本地队列和全局队列Gidle -> Grunnable: 初始化g,放入go池Grunnable -> Grunning: 从go池取出,绑定M,执行实际代码Grunning-> Gdead: 解绑M,重置g,重新放入go池-> Gwaiting: 解绑M,等待被唤醒-> Grunnable: 解绑M,放入go全局队列Gwaiting -> Grunable: 被唤醒后放入go池。原创 2024-08-01 22:42:20 · 1059 阅读 · 0 评论 -
Golang栈空间管理
连续栈核心原理是当当前栈内存不足时,会触发中断,从而分配更大充足的栈空间,并迁移原栈内容到新栈。此外,除了扩容,连续栈还会在已使用的栈空间未超过了总可用空间的四分之一,将新栈收缩到原来的一半。在Go1.3之前,所有goroutine在初始化时都会分配一块固定大小的内存空间。分段栈能够按需为当前goroutine分配内存,并及时减少内存占用,但。迁移过程会被指针也同样迁移过来,不过没关系根据逃逸分析不变性——,所以指向栈中变量的指针只能在栈上。与堆类似,栈也有全局和局部栈空间。原创 2024-07-05 20:30:00 · 369 阅读 · 0 评论 -
Go堆内存管理
heapArena: heapArena 是由 mheap 管理的更小的内存块。按 Span class 对 Span 分类,串联成链表,当 mcache 的某个级别 Span 的内存被分配光时,它会向 mcentral 申请 1 个当前级别的 Span。微分配器将多个微小块分配请求合并到同一个内存块中,只有当内存块中的所有对象都需要被回收时,整片内存才可能被回收。mcache: 每个P所有的cache,包含多个空闲内存块链表,不同的链表上的内存块大小可能是不相同的。Go按照不同对象大小有不同的分配逻辑。原创 2024-07-05 14:48:04 · 899 阅读 · 0 评论 -
go内存返还系统相关代码
在go中内存返还系统相关代码主要由sysUnusedOS实现在Linux中默认是通过madvice方法的_MADV_FREE进行释放,在这种释放中内存其实是被延迟回收的。sysUnusedOS被scavengeOne调用,scavengeOne在给定的内存块(chunk)中搜索可回收的连续页面,并尝试回收指定数量的内存值得注意的是,在回收之后内存还是可以再次分配的scavengeOne继而被scavenge调用该过程分块进行,从最高地址开始,一直持续到清除指定字节数(nbytes)或耗尽堆。原创 2024-07-05 21:00:00 · 861 阅读 · 0 评论 -
go string 实现
在go中string是不可变的,这意味着对string发生改变的操作实际上都是通过分配新的string去实现的在string内存分配上,对于小对象分配到栈,大对象分配到堆中string在go中的结构其实很简单,就是一个指向实际数据的指针以及字符串的长度。原创 2024-05-24 17:53:45 · 426 阅读 · 0 评论 -
golang http2客户端处理逻辑分析
流的状态会随着帧(Frame)的发送和接收而改变。客户端连接通过判断是否超出最大并发流限制去创建新流处理,一个请求通过是否有可复用的客户端连接来判断是否要重新创建,而流是不能被复用的。连接池中不存在已经建立的连接,或者连接不能再承载新请求了(比如已经创建的流数量+等待的请求*2已经超过了int32的最大值)客户端连接在创建之后,开启新协程,从帧处理器循环读取帧,流的缓存管道绑定响应体后,数据被添加到对应流的缓存管道中。一个客户端连接对应一个网络连接,一个客户端连接对应多个流,而一个请求对应一个流。原创 2024-05-17 14:01:25 · 1231 阅读 · 0 评论 -
golang testing使用
汇报自定义度量值如果度量值是每次迭代的,你应该将其除以b.N。按照惯例,单位应该以 “/op” 结尾。会覆盖同一单位的任何先前报告的值。如果单位是空字符串,或者单位包含任何空格,会引发 panic。如果单位是基准测试框架本身通常报告的单位(如 “allocs/op”),会覆盖该度量值。将 “ns/op” 设置为 0 将禁止该内置度量值。for i := 0;i < b.N;原创 2024-05-07 21:15:00 · 1120 阅读 · 0 评论 -
golang 随机数演化
Source接口定义为缩短的63位,这并不是现代生成器的uint64。原创 2024-05-07 20:15:00 · 702 阅读 · 0 评论 -
golang netpoller揭秘
netpoller依托于go调度器,提供了一种看上去同步的异步网络编程模式,显著地降低了开发难度更重要的是,go主动挂起goroutine等待网络IO的完成,而不是被动让系统线程去挂起,这就将执行网络IO的goroutine掌控在Go运行时中。原创 2024-04-28 22:30:00 · 772 阅读 · 0 评论 -
golang sync pool
sync.Pool是内置对象池技术,可用于缓存临时对象,避免因频繁建立临时对象所带来的消耗以及对GC造成的压力在很多知名框架中都可以看到sync.Pool的大量使用。比如Gin中用sync.Pool来复用每个请求都会创建的对象但是值得注意的是sync.Pool缓存的对象可能被无通知的清理。原创 2024-04-25 15:04:37 · 1108 阅读 · 0 评论 -
golang sudog是什么?
sudog代表在等待队列中的goroutine,比如channel发送接受。由于goroutine和同步对象的关系是多对多,因此需要sudog映射。原创 2024-02-02 15:34:03 · 1144 阅读 · 0 评论 -
sync.Cond 源码分析
sync.Cond采用一个L锁进行保护条件变量,并使用通知队列来堵塞和通知goroutine。原创 2024-02-02 15:30:51 · 478 阅读 · 0 评论 -
为什么golang不支持可重入锁呢?
而其他需要用到的场景,可以通过参数控制是否加锁、或者将递归调用函数提取到新函数中交予新函数加锁、或者采用channel之类的来迂回达成可重入锁的目的。那么在实际开发工程中就可能存在虽然是同一个goroutine运行,但是在一个方法内很难知道其他方法是否也用了这个锁,用来做什么。那么重入锁在此时便无法保证保护不变量。比如说存在两个接口方法A、B,A中调用了B,但是由于这两个方法都可能被其他方法所调用,所以如果没有可重入锁便可能会死锁。在工程中使用锁的原因在于为了保护不变量,也可以用于保护内、外部的不变量。原创 2024-02-01 18:22:24 · 1242 阅读 · 0 评论 -
golang map真有那么随机吗?——map遍历研究
在随机选取map中元素时,本想用map遍历的方式来返回,但是却并没有通过测试。那么难道map的遍历并不是那么的随机吗?以下代码参考go1.18hiter是map遍历的结构,主要记录了当前遍历的元素、开始位置等来完成整个遍历过程mapiterinit为开始遍历的方法,主要是确定初始遍历的位置从上面的代码分析我们便可以看出随机选取的元素并不是真的随机,溢出桶并不包含在随机选择的范围里面在具体的遍历过程,存在以下疑问通过以上代码分析,可以看出:在扩容时遍历,如果当前遍历的桶已经迁移好了,那么取新桶。原创 2024-01-25 22:45:00 · 1202 阅读 · 0 评论 -
make和new的区别
make和new都是golang用来分配内存(理论上都是在堆上分配),不同的是。原创 2023-10-30 16:19:26 · 189 阅读 · 0 评论 -
for与for range
传统的for和for range是golang唯二提供的能够遍历的循环结构,但是for range并不是简单的for语法糖,实际上他们之间仍然有很大的不同。原创 2023-09-11 14:38:01 · 188 阅读 · 0 评论 -
delve如何使用?
在mac下安装设置开发者模式加入当前用户到开发组进入所在目录,输入dlv debug进入调试断点clearclearall流程控制continuenextstepstepout参数查看argslocalsvarsregsgoroutine和线程goroutinegoroutinesthreadthreads。原创 2023-09-04 20:56:39 · 212 阅读 · 0 评论 -
docker镜像是如何导入的?
镜像导入是由image/tarexport/load.go#tarexporter.Load()完成的以下代码参考github.com/docker/docker版本v0.0.0-20181129155816-baab736a3649主要是注册镜像信息以及解包镜像tar流到新root导出和保存的区别在于这意味着导出将不会包含USER、EXPOSE等Dockerfile里面的命令,也就无法转移镜像到另一台机器上了。原创 2023-09-02 23:04:27 · 1283 阅读 · 0 评论 -
为什么没有goroutine id
对于从Java、C之类转到Go的程序员而言,获取线程id是一件自然而然的事情,但是在Go里面却不一样,那么为什么goroutine没有id呢?以下是我搜罗到的没有goroutine id的主要观点一旦开发者命名了一个goroutine并围绕建立模型,那么该goroutine就会变得极为特殊,而忽略了多个goroutine共同处理的可能性防止线程本地储存被滥用。新goroutine突然无法访问父goroutine的本地储存,这可能会引起问题。原创 2023-07-18 23:26:43 · 256 阅读 · 0 评论 -
H2O生成——屏障
H2O生成是只有同时存在且仅存在的情况下两个氢原子和一个氧原子,才能生成下一个氢原子或者氧原子,如此循环往复。原创 2023-04-28 23:12:32 · 959 阅读 · 0 评论 -
Golang Mutex怎么实现互斥的?
Mutex是Golang常见的并发原语,不仅在开发过程中经常使用到,如channel这种具有golang特色的并发结构也依托于Mutex从而实现Mutex有正常饥饿模式。正常模式:等待者会入队,但一个唤醒的等待者不能持有锁,以及与新到来的goroutine进行竞争。新来的goroutine有一个优势——他们已经运行在CPU上。超过1ms没有获取到锁,就会进入饥饿模式。原创 2023-04-20 15:45:11 · 629 阅读 · 1 评论 -
go map怎么搬迁的?
在本次搬迁进度是最新进度的情况下(不是最新就让最新的去干吧)更新进度尝试往后看1024个bucket,如果发现有搬迁完的,但是没更新进度就顺便帮别人更新了若是全部bucket都完成搬迁了,那就直接将原buckets释放掉。原创 2023-04-14 20:29:28 · 687 阅读 · 0 评论 -
Go Channel是什么?
因为关闭channel的时候会唤醒所有等待的发送goroutine,并继续执行堵塞之后的逻辑,发现goroutine是被关闭后唤醒的就会panic。将锁分散在对象图中听起来像一场噩梦,但若是channel则是被期望,被鼓励的。从上面结构可以看出,channel是一个拥有锁的双向队列,储存了数据、缓冲、等待接收发送队列等。为什么在发送关闭的channel会panic,而接收关闭的channel则会接收到零值呢?我认为这句话很有意思,并发是我们代码能保证的,可是并行的事情得交给机器来处理。原创 2023-04-12 00:05:17 · 312 阅读 · 0 评论 -
Go 垃圾回收
垃圾回收负责跟踪堆内存分配,释放不再需要的内存,保存仍在使用的内存。原创 2023-02-22 11:09:32 · 337 阅读 · 0 评论 -
信号量——以golang为例
信号量是一个变量或者抽象数据类型,被用于控制在并发系统临界区问题多个线程对公共资源的访问。与自旋锁、栅栏一起作为同步手段。一个普通的信号量是单纯取决于程序员定义条件而改变的变量允许任意资源计数的信号量称为计数信号量,而限制为0和1(或锁定/解锁,不可用/可用)值的信号量称为二进制信号量,用于实现锁。我们可以将信号量看作记录特定资源的数量记录,并耦合调整该记录的安全操作。数量记录,即意味着信号量并不记录哪些资源可以操作使用信号量时,有很多行为需要注意。原创 2023-02-12 10:45:00 · 1290 阅读 · 0 评论 -
golang sync.Cond基本使用
sync.Cond条件变量用来协调访问共享资源的goroutine,当共享资源状态发生改变时,用于通知被互斥锁堵塞的goroutinesync.Cond主要多个读协程等待共享资源可用时非常有用sync.Cond c主要方法有Broadcast: 唤醒所有等待c的goroutine。允许但不要求调用者持有c的锁Signal: 只唤醒一个等待的goroutine。允许但不要求调用者持有c的锁Wait: 挂起调用者goroutine等待被Signal、Broadcast唤醒。原创 2023-02-04 14:13:32 · 187 阅读 · 0 评论 -
Golang rune与int32的区别
截取出来并不是“好”,所以需要将字符转换为rune,然后再转为string就可以得到期望中的中文字符。实际上当我们将字符转换为int32,转换回string也会得到同样期待中的中文字符。可能就是名字吧,rune让人想到字符,而int32使人想到数字。rune主要是用来处理unicode字符的,比如说。golang rune和int32有什么区别呢?从源码可知rune实际上就是int32的别名。那么rune到底和int32有什么区别呢?rune实际上就是int32。原创 2023-02-04 13:38:46 · 448 阅读 · 0 评论 -
go sync map
sync.Map相当于goroutine并发安全的Map。sync.Map针对两种常见情况进行了优化sync.Map在第一次使用后不能被复制过程展现最开始写入数据只会到dirty中,因为dirty主要接受写数据。此时read amended为true读取时从read读取,此时read并没有数据,misses记录从read读取失败的次数,当misses大于等于dirty数据量时,将dirty升级为read。升级也就是对dirty进行地址拷贝并且dirty清空,misses置为0。原创 2022-10-27 11:08:10 · 248 阅读 · 0 评论 -
Go GMP了解
M: thread 线程P: Processor 包含运行goroutine的资源。原创 2022-08-16 13:32:25 · 460 阅读 · 0 评论 -
Golang DNS 随便写写
golang具有内置go解析器以及基于cgo的系统解析器两种DNS解析方式其中在Linux下默认是go内置go解析器域名系统( DNS)是一种用于 TCP/IP 应用程序的分布式数据库,它提供主机名字和IP地址之间的转换及有关电子邮件的选路信息从应用的角度上看,对 DNS的访问是通过一个地址解析器( resolver )来完成的。解析器并不像 TCP/IP 协议那样是操作系统的内核。当nameResolver发出查询请求,并且返回响应中的TC(删减标准)为1时,意味着响应长度超过了512字节,而仅返回前51原创 2022-07-05 16:49:30 · 1718 阅读 · 0 评论 -
Golang defer
在Golang使用defer常常会迷惑于以下两个问题的调用时机是在当前函数返回之前调用的,执行顺序是先入后出。也是传参的。比如说以下代码就会输入0,而不是最终的1其原因在于会立刻拷贝defer函数中引用的外部参数,也就是说运行到时,n的值便已经在defer函数里面啦如果想避免这种情况我们可以defer匿名函数或者指针参数函数常见defer现象连续defer,先入后出按照先入后出执行defer声明,变量确认变量在defer声明时便已经确认,即使后面变量发生改变,defer实际执行时也与声明时保持一原创 2022-06-28 21:34:14 · 239 阅读 · 0 评论 -
Golang 类型比较
基本类型比较中变量类型必须相等(即使是int、int32这种也是不能比较的)也即对于数组而言,要求数组中所有数据必须是可比较的,且数组长度也要一致总之对于能比较数组必须满足结构体类型只要结构成员是能比较的,那么结构体就能比较指针类型指针类型是基本类型指针以及slice、map。对于基本类型指针比较的是指针指向的是否为同一个地址而slice、map则无法比较interface{}类型接口比较的是动态类型以及动态值,只有两者都相等时,比较才相等。如果动态类型不能比较的话,那么也会不相等函数类型原创 2022-06-28 21:05:12 · 787 阅读 · 0 评论 -
Golang Modules
在$GOPATH/src之外的文件夹(比如//hello),创建全新的go文件,比如说hello.go。并且让我们为他写个test。运行之后会发现因为我们工作在 和任意模块之外,go 命令不知道当前目录的导入路径(导入路径是标识包的唯一字符串标识)所以根据目录所在位置创建了一个假的导入路径 让我们使用将文件夹初始化为module吧!将会写go.mod文件go命令通过使用go.mod中列出特定依赖模块版本来解析导入。当go.mod未指定时,会自动找到最新依赖,添加到go.mod当然除了go.mod中列出的原创 2022-06-12 20:35:42 · 228 阅读 · 0 评论 -
Go context 基本介绍
在Go1.7中引入了context,包含goroutine运行状态、环境、现场等信息。并逐渐成为并发控制、超时控制的标准做法。原创 2022-06-12 20:31:13 · 335 阅读 · 0 评论 -
grpc 基本使用
grpc是由google开发的一款语言中立、平台中立、开源的RPC系统在grpc中客户端应用可以像调用本地对象一样直接调用另一台不同机器上服务端应用的方法,使得很容易创建分布式应用和服务。与许多RPC系统类似,grpc也是定义一个服务,指定能够被远程调用的方法,在服务端实现该接口,并允许grpc服务器来处理客户端调用。客户端拥有像服务端一样方法的stub。grpc允许定义四种服务方法单项RPC,即客户端发送一个请求给服务端,然后从服务端获取一个应答,就像一次普通的函数调用服务端流式RPC,客户端原创 2022-05-12 21:00:57 · 1259 阅读 · 0 评论 -
Golang 类型转换
将一个值从一种类型转换到另一种类型,便发生了类型转换。静态语言如c/c++,Java提供了隐性的类型转换,但对于golang这种强类型系统则不一样,golang并不支持自动类型转换或者隐性类型转换。在go可以分为断言、强制、显式类型转换。通常说的类型转换是指断言,强制一般不会用到,显式是基本的类型转换断言断言通过判断接口x是否不是nil且为T类型var s = x.(T)具体而言,在T不为接口时,要求x的动态类型就是T,并且T必须实现了x接口;否则类型断言无效,因为x不可能储存类型T的值动原创 2022-04-19 22:37:18 · 3881 阅读 · 0 评论