
Go语言设计与实现
文章平均质量分 89
吃着火锅x唱着歌
这个作者很懒,什么都没留下…
展开
-
Go语言设计与实现 学习笔记 第九章 标准库
作为标准库的JSON提供的接口非常简洁,虽然它的性能一直被开发者所诟病,但作为框架它提供了很好的通用性,通过分析JSON库的实现,我们也可以从中学习到使用反射的各种方法。默认情况下,当我们在序列化和反序列化结构体时,标准库都会认为字段名和JSON中的键具有一一对应的关系,然而Go语言的字段一般都是驼峰命名法,JSON中下划线的命名方式相对比较常见,使用标签特性可以建立键与字段之间的映射关系。我们在这里会简单介绍JSON标准库中的接口和标签,这是它为开发者提供的为数不多的影响编解码过程的接口。原创 2024-09-26 00:59:00 · 905 阅读 · 1 评论 -
Go语言设计与实现 学习笔记 第八章 元编程
熟悉Go语言的开发者一般都非常了解Goroutine和Channel的原理,包括如何设计基于CSP模型(该模型中的并发实体通过消息传递来通信,而不是共享内存)的应用程序,但Go的插件系统是一个很少有人了解的模块,通过插件系统,我们可以在运行时加载动态库实现一些比较有趣的功能。Go语言的代码生成机制会读取包含预编译指令的注释,然后执行注释中的命令读取包中的文件,它们将文件解析成抽象语法树并根据语法树生成新的Go语言代码和文件,生成的代码会在项目的编译期间与其它代码一起编译和运行。原创 2024-09-23 23:50:27 · 1206 阅读 · 0 评论 -
Go语言设计与实现 学习笔记 第七章 内存管理(2)
扫描对象运行时会使用runtime.gcDrain函数扫描工作缓冲区中的灰色对象,它会根据传入gcDrainFlags的不同选择不同的策略:// 清空垃圾收集器的工作缓冲区func gcDrain(gcw *gcWork, flags gcDrainFlags) { // 获取当前M上运行的Goroutine gp := getg().m.curg // 清空操作是否可被抢占 preemptible := flags&gcDrainUntilPreempt !=原创 2024-09-22 13:14:41 · 972 阅读 · 1 评论 -
Go语言设计与实现 学习笔记 第七章 内存管理(1)
7.1 内存分配器程序中的数据和变量都会被分配到程序所在的虚拟内存中,内存空间包含两个重要区域——栈区(Stack)和堆区(Heap)。函数调用的参数、返回值、局部变量大都会被分配到栈上,这部分内存会由编译器进行管理;不同编程语言使用不同的方法管理堆区的内存,C++等编程语言会由工程师主动申请和释放内存,Go以及Java等编程语言会由工程师和编译器共同管理,堆中的对象由内存分配器分配并由垃圾收集器回收。不同的编程语言会选择不同的方式管理内存,本节会介绍Go语言内存分配器,详细分析内存分配的过程以及其背后原创 2024-09-17 13:41:43 · 943 阅读 · 1 评论 -
Go语言设计与实现 学习笔记 第六章 并发编程(3)
会返回可读或者可写事件(如上,还有异常事件)的个数,应用程序就可以在输入的文件描述符中(实际上,select函数会通过参数返回哪些fd可用,例如通过readfds参数返回可读的fd集合,通过writefds参数返回可写的fd集合)查找哪些可读或可写(或异常),然后执行相应的操作。Go语言的系统监控也起到了很重要的作用,它在内部启动了一个不会中止的循环,在循环的内部会轮询网络、抢占长期运行或处于系统调用的Goroutine、触发垃圾回收,通过这些行为,它能够让系统的运行状态变得更健康。原创 2024-09-07 17:53:18 · 1236 阅读 · 1 评论 -
Go语言设计与实现 学习笔记 第六章 并发编程(2)
SingleFlightsingleflight是Go语言扩展包中提供的另一种同步原语,它能够在一个服务中抑制对下游的多次重复请求,一个比较常见的使用场景是——我们使用Redis对数据库中的一些热门数据进行缓存并设置了超时时间,缓存超时的一瞬间可能有非常多的并行请求发现了Redis中已经不包含任何缓存,所以大量的流量会打到数据库上影响服务的延时和质量。但是singleflight就能有效解决这个问题,它的主要作用是对同一个Key最终只进行一次函数调用,在这个上下文中就是只会进行一次数据库查询,查询的结原创 2024-09-01 18:16:14 · 1198 阅读 · 0 评论 -
Go语言设计与实现 学习笔记 第六章 并发编程(1)
(Wait不就应该等待其他Goroutine并发执行结束吗,并发执行结束时的Done中不就调用了Add吗?互斥锁可以同时处于两种不同的模式(作者说一个互斥锁可以同时处于两种模式,实际上在某一时刻,锁只能是两种模式之一,由上图中的starving部分控制,但在锁的生命周期内,两种模式可以互相切换),也就是正常模式和饥饿模式,在正常模式下,所有锁的等待者都会按照先进先出的顺序获取锁,但是如果一个刚刚被唤起的Goroutine遇到了新的Goroutine也调用了。原创 2024-08-01 12:25:51 · 424 阅读 · 0 评论 -
Go语言设计与实现 学习笔记 第五章 常用关键字(2)
的作用是根据传入的类型在堆上分配一片内存空间并返回指向这片内存空间的指针(作者说new会在堆上分配空间,其实这是不对的,go的new比较特殊,其他语言中的new常常是在堆上分配内存,但go会根据逃逸分析的结果决定是在栈上还是堆上分配内存);分析的过程设计了很多语言底层的知识,源代码阅读起来也比较晦涩,其中充斥着反常规的控制流程,通过程序计数器来回跳转,不过对于我们理解程序的执行流程还是很有帮助的。因为它们的功能相似,所以初学者可能会对这两个关键字的作用感到困惑,它们两者的确有较大的不同。原创 2024-07-08 13:14:16 · 950 阅读 · 0 评论 -
Go语言设计与实现 学习笔记 第五章 常用关键字(1)
5.1 for和range循环是所有编程语言都有的控制结构,除了使用经典的“三段式”循环之外,Go语言还引入了另一个关键字range帮助我们快速遍历数组、切片、哈希表以及Channel等集合类型。本节将深入分析Go语言的两种不同循环,也就是经典的for循环和for/range循环,我们会分析这两种循环的运行时结构以及它们的实现原理。for循环能够将代码中的数据和逻辑分离,让同一份代码能够多次复用处理同样的逻辑。我们先来看一下Go语言for循环对应的汇编代码,下面是一段经典的三段式循环的代码,我们将它编译原创 2024-07-08 01:00:59 · 1031 阅读 · 0 评论 -
Go语言设计与实现 学习笔记 第四章 语言基础(2)
准备参数的过程是计算各个参数和返回值占用的内存空间并将所有的参数都拷贝到内存空间对应位置的过程,该过程会考虑函数和方法、返回值数量以及参数类型带来的差异。(不太清楚这里的m和n分别表示什么,应该分别是接口和类型的方法数量,这里的时间复杂度应该是O(n),n为类型的方法数,因为循环中遍历的只是v的方法集)。在上述方法中,会检查传入参数的个数以及参数的类型与函数签名中的类型是否匹配,任何参数的不匹配都会导致整个程序的崩溃中止。并返回一个新的反射对象,这个返回的反射对象指针就会直接覆盖原始的反射变量。原创 2024-06-23 23:12:19 · 862 阅读 · 0 评论 -
Go语言设计与实现 学习笔记 第四章 语言基础(1)
Go语言虽然不是严格意义上的面向对象语言,但是接口的引入为它带来了动态派发这一特性,调用接口类型的方法时,如果编译期间不能确认接口的类型,Go语言会在运行期间决定具体调用该方法的哪个实现。错误,仔细思考一下就能够发现出错的原因,Go语言的函数调用都是值传递的,所以我们得到的反射对象跟最开始的变量没有任何关系,所以直接对它修改会导致崩溃(简单来说,错误的原因在于试图直接修改一个非指针类型reflect.Value的值,v是由i的副本创建的,所以v不可寻址,也不能被修改)。反射是Go语言比较重要的特性。原创 2024-06-21 20:14:02 · 1162 阅读 · 0 评论 -
Go语言设计与实现 学习笔记 第三章 数据结构(2)
类型的关系,从词法分析阶段理解字符串是如何被解析的,作为只读的数据类型,我们无法改变其本身的结构,但是在做拼接和类型转换等操作时一定要注意性能的损耗,遇到需要极致性能的场景一定要尽量减少类型转换的次数。随着键值对数量的增加,溢出桶的数量和哈希的装载因子也会逐渐升高,超过一定范围就会触发扩容,扩容会将桶的数量翻倍,元素再分配的过程也是在调用写操作时增量进行的,不会造成性能的瞬时巨大抖动。中的内容是可以读写的,无论从哪种类型转换到另一种都需要对其中的内容进行拷贝,而内存拷贝的性能损耗会随着字符串和。原创 2024-06-12 13:01:37 · 709 阅读 · 0 评论 -
Go语言设计与实现 学习笔记 第三章 数据结构(1)
3.1 数组数组和切片是Go语言中常见的数据结构,很多刚刚使用Go的开发者往往会混淆这两个概念,数组作为最常见的集合在编程语言中是非常重要的,除了数组之外,Go语言引入了另一个概念——切片,切片与数组有一些类似,但是它们的不同之处导致使用上会产生巨大的差别。我们在这一节中会从Go语言的编译期间和运行时来介绍数组的底层实现原理,其中会包括数组的初始化、访问和赋值几种常见操作。3.1.1 概述数组是由相同类型元素的集合组成的数据结构,计算机会为数组分配一块连续的内存来保存其中的元素,我们可以利用数组中元素原创 2024-06-09 21:19:59 · 1421 阅读 · 1 评论 -
Go语言设计与实现 学习笔记 第二章 编译原理
早期的CPU为了减少机器语言指令的数量使用复杂指令集完成计算任务,这两者其实并没有绝对的好坏,它们只是在一些设计上的选择不同以达到不同的目的,我们会在后面的机器码生成一节中详细介绍指令集架构,不过各位读者也可以主动了解相关的内容。所有的编译过程其实都是从解析代码的源文件开始的,词法分析的作用就是解析源代码文件,它将文件中的字符串序列转换成Token序列,方便后面的处理和解析,我们一般会把执行词法分析的程序称为词法解析器(lexer)。原创 2024-04-24 14:40:49 · 1168 阅读 · 0 评论 -
Go语言设计与实现 学习笔记 第一章 介绍
Go语言是Google在2009年12月发布的编程语言,目前的Go语言在国内外的社区都非常热门,很多著名的开源框架Kubernetes(K8s,一个开源的容器编排平台,它旨在简化容器化应用程序的部署、扩展和管理)、etcd(一个开源的分布式键值存储系统)和prometheus(一个开源的系统监控和警报工具包)等都使用Go语言进行开发,近年来热门的微服务架构和云原生技术也为Go语言社区带来了非常多的活力。3.理解Go语言中的函数、方法、闭包和上下文等语言特性;原创 2024-04-20 22:56:25 · 435 阅读 · 0 评论