![](https://img-blog.csdnimg.cn/20201014180756925.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
Go设计与实现
文章平均质量分 80
胡桃姓胡,蝴蝶也姓胡
非常熟悉service mesh,有共同兴趣的小伙伴可以私信我
展开
-
Go语言设计模式 -- 责任链模式
在阅读dubbogo流量管控的源码过程中,遇到了这个设计模式,所以做一下记录。原创 2023-04-26 17:24:56 · 173 阅读 · 0 评论 -
Go的IO -- Go语言设计与实现
协程是Go的很大的一个优势。Go天然支持高并发,那么我们来研究一下这个高并发的秘诀在哪里?。CPU 不停的在不同的执行体( Goroutine )之间反复横跳!CPU 一直在装填和运行不同执行体的指令,G1(Goroutine 1 的缩写) 不行就搞 G2 ,一刻不能停,这样才能使得大量的执行体( Goroutine )齐头并进,系统才能完成如此高的吞吐(注意关键字:并发哦)。思考一个问题,程序可以分成CPU密集型合IO密集型,Go适合哪一种?很明显IO密集型,CPU密集型只能买核,买CPU,别无他法。原创 2023-04-10 17:25:01 · 918 阅读 · 1 评论 -
工作中遇到的问题 -- Go避免内存拷贝的强制类型转换
name :=(string)("我真的很喜欢你")由于第一个括号里面是一个指针类型,那么第二个括号里面肯定是指针的值。而通过就可以将&msg指针的内存地址取出来。两个括号合起来就是,声明并定义了一个类型的指针变量,对应的指针值还是原来 msg1 的内存地址。那最前面的的那个那个,大家应该都知道,是从类型的指针变量中取出值。然后我们来看一下同样的,则是切片的底层数据结构对咯,只要把里的 Data 塞给里的 Data,再把里的 Len 塞给。原创 2023-03-08 17:54:12 · 414 阅读 · 0 评论 -
Go语言设计与实现 -- http服务器编程
http 是典型的 C/S 架构,客户端向服务端发送请求(request),服务端做出应答(response)。golang 的标准库net/http提供了 http 编程有关的接口,封装了内部TCP连接和报文解析的复杂琐碎的细节,使用者只需要和和两个对象交互就行。也就是说,我们只要写一个 handler,请求会通过参数传递进来,而它要做的就是根据请求的数据做处理,把结果写到 Response 中。废话不多说,来看看 hello world 程序有多简单吧!我们先把注意力聚焦到/way2上,先暂时不看。原创 2023-03-07 22:30:54 · 573 阅读 · 1 评论 -
Go语言设计与实现 -- 反射
尽管 i,j 的底层类型都是 int,但我们知道,他们是不同的静态类型,除非进行类型转换,否则,i 和 j 不能同时出现在等号两侧。接着,使用反射,获取x,y 的反射对象,并且立即比较两者的类型,根据前面的内容,这里实际上是动态类型,如果类型不同,直接返回 false。赋一个 int 类型的值时,它的静态类型还是 interface{},这是不会变的,但是它的动态类型此时变成了 int 类型。先明白一点,如果是不同的类型,即使是底层类型相同,相应的值也相同,那么两者也不是“深度”相等。原创 2023-02-18 16:57:29 · 801 阅读 · 0 评论 -
Go的GC回收的堆还是栈,我们用实验来说明
由于堆局部变量做了处理,使其确定在堆上分配,就被回收了,由此证明GO的GC只回收堆上的内存。原创 2023-02-09 23:59:21 · 717 阅读 · 0 评论 -
Go语言设计与实现 -- 栈空间管理
Go 语言的汇编代码包含 BP 和 SP 两个栈寄存器,它们分别存储了栈的基址指针和栈顶的地址,栈内存与函数调用的关系非常紧密,我们在函数调用一节中曾经介绍过栈区,BP 和 SP 之间的内存就是当前函数的调用栈。原创 2023-01-10 15:14:42 · 587 阅读 · 0 评论 -
Go语言设计与实现 -- 浅谈垃圾回收机制
虽然高级垃圾收集器解决了Java中的实际问题,但现代语言,如Go和Julia,从一开始就避免了这些问题,因此不需要使用Rolls Royce垃圾收集器。当您有了值类型、转义分析、指针、多核处理器和现代分配器时,Java设计背后的许多假设都被抛到了脑后。它们不再适用。基于以上理由,Go的GC和Java的GC还是很有不同的。原创 2023-01-09 20:27:06 · 1645 阅读 · 0 评论 -
Go语言设计与实现 -- GC的简要介绍
垃圾回收也称为GC(Garbage Collection),是一种自动内存管理机制现代高级编程语言管理内存的方式分为两种:自动和手动,像C、C++ 等编程语言使用手动管理内存的方式,工程师编写代码过程中需要主动申请或者释放内存;而 PHP、Java 和 Go 等语言使用自动的内存管理系统,有内存分配器和垃圾收集器来代为分配和回收内存,其中垃圾收集器就是我们常说的GC。原创 2023-01-09 12:56:00 · 563 阅读 · 0 评论 -
Go语言设计与实现 -- 内存对齐机制
为了能让CPU可以更快的存取到各个字段,Go编译器会帮你把struct结构体做数据的对齐。所谓的数据对齐,是指内存地址是所存储数据的大小(按字节为单位)的整数倍,以便CU可以一次将该数据从内存中读取出来。编译器通过在结构体的各个字段之间填充一些空白已达到对齐的目的。原创 2023-01-08 23:54:57 · 447 阅读 · 0 评论 -
Go语言设计与实现 -- 内存逃逸
栈上分配内存比在堆中分配内存效率更高栈上分配的内存不需要GC处理,而堆需要逃逸分析的目的是确定内存分配地址是栈还是堆逃逸分析在编译阶段完成无论变量的大小,只要是指针变量都会在堆上分配,所以对于小变量我们还是使用传值效率更高一点。原创 2023-01-08 23:14:18 · 368 阅读 · 0 评论 -
Go语言设计与实现 -- 内存管理器
首先通过计算使用的大小规格然后使用mcache中对应大小规格的块分配。如果mcentral中没有可用的块,则向mheap申请,并根据算法找到最合适的mspan。如果申请到的mspan超出申请大小,将会根据需求进行切分,以返回用户所需的页数。剩余的页构成一个新的 mspan 放回 mheap 的空闲列表。如果 mheap 中没有可用 span,则向操作系统申请一系列新的页(最小 1MB)原创 2023-01-07 22:05:07 · 490 阅读 · 0 评论 -
Go语言设计与实现 --调度器(详细介绍)
代表Go 协程Goroutine,存储了 Goroutine 的执行栈信息、Goroutine 状态以及 Goroutine 的任务函数等。,创建一个 G 的初始栈大小为2-4K,配置一般的机器也能简简单单开启数十万个 Goroutine ,而且Go语言在 G 退出的时候还会把 G 清理之后放到 P 本地或者全局的闲置列表 gFree 中以便复用。: Go 对操作系统线程(OS thread)的封装,可以看作操作系统内核线程,想要在 CPU 上执行代码必须有线程,通过系统调用 clone 创建。原创 2023-01-06 18:47:40 · 1017 阅读 · 0 评论 -
Go语言设计与实现 --Goroutine
Goroutine是GMP模型中的G,是属于用户态的线程,由Go runtime管理,而不是操作系统管理。原创 2023-01-06 15:59:15 · 1027 阅读 · 2 评论 -
Go语言设计与实现 -- 调度器总体概述
Go语言调度器使用与CPU数量相等的线程来减少线程频繁切换带来的内存开销,同时在每一个线程上执行额外开销更低的Goroutine来降低操作系统和硬件的负载。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R6k4OOSm-1672989679772)(D:\A\图片\板书\调度器.excalidraw.png)]每一次线程上下文切换都需要消耗约1us的时间,而Go调度器对Goroutine的上下文的切换约为0.2us,减少了80%的额外开销!原创 2023-01-06 15:25:01 · 601 阅读 · 0 评论 -
Go语言设计与实现 -- Channel
队列中包含处于等待状态的 Goroutine 时,该函数会取出队列头等待的 Goroutine,处理的逻辑和发送时相差无几,只是发送数据时调用的是 runtime.send。当 Channel 的发送队列中不存在等待的 Goroutine 并且缓冲区中也不存在任何数据时,从管道中接收数据的操作会变成阻塞的,然而不是所有的接收操作都是阻塞的,与。除此之外,该函数还会减少。所在位置的元素,原有的元素会被拷贝到接收数据的变量对应的内存空间上。将缓冲区中的数据复制到内存中,清除队列中的数据并完成收尾工作。原创 2023-01-04 20:54:19 · 1051 阅读 · 5 评论 -
Go语言设计与实现 -- sync.Pool
一句话总结:保存和复用临时对象,减少内存分配,降低GC压力sync.Pool是可伸缩的,也是并发安全的,其大小仅受限于内存大小。sync.Pool用于存储那些被分配了但是没有使用,而未来可能会使用的值。这样就可以不用再次经过内存分配,可直接复用已有对象,减轻GC的压力,从而提升系统性能。原创 2022-12-30 16:58:39 · 155 阅读 · 0 评论 -
Go语言设计与实现 -- singleflight
放弃使用同步请求,牺牲数据更新的实时性“缓存” 存储准实时的数据 + “异步更新” 数据到缓存。原创 2022-12-29 16:55:28 · 1252 阅读 · 4 评论 -
Go语言设计与实现 -- WaitGroup, Once, Cond
我们可以通过 sync.WaitGroup将原本顺序执行的代码在多个 Goroutine 中并发执行,加快程序处理的速度。我们来看一下是WaitGroup里面需要等待的Goroutine的数量waiter和sema是信号量。必须在Wait方法返回之后才能重新使用Done方法只是对Add的简单封装。我们可以向Add方法传入任意负数,快速将计数器归零以唤醒等待的Goroutine。但是需要注意的是:计数器非负,如果计数器是负数,那么程序就会直接崩溃可以有多个Goroutine等待当前计数器归零,这些。原创 2022-12-29 14:54:02 · 364 阅读 · 0 评论 -
Go语言设计与实现 -- RWMutex分析
不限制资源的并发读,但是读写和写写操作无法并行执行。是读写互斥锁。原创 2022-12-29 12:56:00 · 367 阅读 · 0 评论 -
Go语言设计与实现 -- Mutex源码剖析
上图中,第一列为常见的同步原语,第二列为容器,第三列为互斥锁。原创 2022-12-28 15:21:07 · 996 阅读 · 0 评论 -
Go语言设计与实现 -- 上下文
我们先来看一下DeadlineDoneChannelChannelContextValueValuekey。原创 2022-12-26 23:10:08 · 732 阅读 · 0 评论 -
Go语言设计与实现 -- make和new
这两种是完全等价的。它们都会创建一个指向。原创 2022-12-24 21:47:47 · 92 阅读 · 0 评论 -
Go语言设计与实现 -- 关键字for和range
如果我们查看汇编代码的话,可以发现,的for-range循环的汇编代码和普通for的结构相同。也就是说,使用for-range的控制结构最终也会被Go语言编译器换成普通的for循环。原创 2022-12-23 22:06:51 · 1273 阅读 · 0 评论 -
Go语言设计与实现 -- 接口
接口实际上是一个中间层,用于上下游的解耦,在框架和操作系统中,接口都随处可见,而Go语言将接口作为了内置类型,接下来,我们就来重点学习一下,Go语言的接口。Go语言只会在传递参数,返回参数,以及变量赋值的时候检查某个类型是否实现了接口。简而言之,就是在需要它的时候才会去检查它与C语言的void *不一样,类型并不是任意类型。如果我们将类型转换成了,变量在运行期间的类型也会随之发生变化,获取变量时会得到。原创 2022-12-21 20:30:50 · 1126 阅读 · 0 评论 -
Go语言设计与实现 -- 函数
Go通过栈传递函数的参数和返回值,在调用函数之前会在栈上为返回值分配合适的内存空间,随便将入参从左按顺序压栈并复制参数,而参数的计算是从右到左的(栈的特性)。原创 2022-12-21 17:05:17 · 411 阅读 · 0 评论 -
Go语言设计与实现 -- 字符串
Go语言的字符串与Java和python是一样的。具有。是一个只读的字节数组,如图所示。因为Go的字符串具有不可变性,所以我们只能通过string和[]byte类型之间反复转换实现修改。原创 2022-12-21 16:10:45 · 381 阅读 · 0 评论 -
Go设计与实现 -- map哈希表
我们先用两张图来全局的查看Go的map。这下大家对哈希表肯定有了全局的概念了,接下来我们来逐一的进行分析:首先是最核心的结构体。原创 2022-12-11 22:26:31 · 702 阅读 · 0 评论 -
Go设计与实现--数组与切片
Go语言数组的初始化是在编译期就已经执行好了。首先解释一下这个函数的返回值,Type是一个什么东西。它表示的是一个类型。其实不光是数组,切片,哈希表等在初始化的时候同样会返回这个Type结构体的指针。以上是Go初始化最本质的代码。这两种在运行时就已经完全一样了,只是Go给我们的语法糖而已。因此我们现在讲一下推导的过程。原创 2022-12-09 11:23:21 · 549 阅读 · 0 评论