go语言原理
文章平均质量分 86
go语言从入门到入土
你是什么品种的萝卜
人生何处不迷雾,东隅已逝,桑榆非晚
展开
-
【go的测试】2.性能测试
性能测试,benchmark,pprof,abtest原创 2024-04-09 22:17:59 · 714 阅读 · 0 评论 -
【go的测试】1.错误测试
1. go的几种测试1. go的几种测试错误测试:模糊测试 fuzzingmockmonkey性能测试:基准性能测试 benchmarkpprofab测试其他第三方工具本章总结的是几种错误测试,性能测试见下节。2. go test 命令参数3. Fuzzing 模糊测试(1)Fuzzing 模糊测试(随机测试)一种基于随机输入的自动化测试技术。Fuzzing不需要像单元测试那样使用预先定义好的数据集作为程序输入,而是会通过数据构造引擎自行构造或基于开发人员提供的初始数据。原创 2024-04-09 21:55:01 · 303 阅读 · 0 评论 -
【go基础】17.系统监控sysmon
Golang的系统监控:go内部启动了一个不会中止的循环,在循环的内部会轮询网络抢占长期运行或者处于系统调用的Goroutine以及触发垃圾回收,通过这些行为,让系统的运行状态变得更健康。主要工作:检查死锁运行计时器:计算与触发计时器轮询网络:管理I/O和网络操作抢占处理器:工作窃取机制,避免线程饥饿问题垃圾回收:定时或内存使用率过高时,触发gc。原创 2024-03-24 16:46:44 · 804 阅读 · 0 评论 -
【go基础】16.I/O模型与网络轮询器netpoller
一、I/O模型在linux世界中,所有I/O设备被抽象为文件Everything is File,都通过文件操作:open 打开;seek 改变读写位置;read write 读写;close 关闭文件描述符(File descriptor,FD):用于访问文件或者其他 I/O 资源的抽象句柄,例如:管道或者网络套接字。不同的 I/O 模型会使用不同的方式操作文件描述符。5种I/O模型:同步的阻塞I/O模型非阻塞I/O模型I/O多路复用模型信号驱动I/O模型异步I/O模型。原创 2024-03-24 16:32:58 · 635 阅读 · 0 评论 -
【go基础】15.定时器Timer, Ticker
调度器调用 runtime.findrunnable 获取可执行的goroutine 或从其他处理器窃取计时器时。每个P拥有一个最小四叉堆,单独管理。交给网络轮询器和调度器触发,较少上下文切换开销。将全局四叉堆分成64个更小的四叉堆,每个处理器(P)创建的计时器由对应的四叉堆维护。后台系统监控(函数runtine.sysmon)会检查是否有未执行的到期计时器。3. go 1.14之后,每个处理器单独管理计时器,并通过网络轮询器触发。这种分片方式降低了锁粒度,提高了性能,但是造成了cpu频繁上下文切换。原创 2024-03-24 16:13:18 · 412 阅读 · 0 评论 -
【go基础】14.sync之ErrGroup, Semaphore, SingleFlight
为一组 goroutine 中做同步、错误提取、上下文取消1、初始化2、Go() 接口启动一个goroutine运行任务,可以返回err3、Wait() 接口对sync.WaitGroup的简单封装4、多个goroutine的错误提取控制访问资源的进程数量,保证持有的计数器在0到初始化的权重之间波动。每次获取资源时都会将信号量中的计数器减去对应的数值,在释放时重新加回来;当遇到计数器大于信号量大小时,会进入休眠等待其他线程释放信号。创建信号量Acquire ——原创 2024-03-22 23:03:40 · 508 阅读 · 0 评论 -
【go基础】13.sync之Map, WaitGroup, Once, Cond, Pool
Map。原创 2024-03-22 22:57:19 · 723 阅读 · 1 评论 -
【go基础】12.unsafe包
intp与floatp 的地址相同,但是指向不同的数据类型,intp指向一个int值,floatp指向一个float32值。由于int类型有64位,float32只有32位,所以将int转换为float32时发生了内存截断,超出位数的部分被丢弃。这使得go语言是类型安全的,所有类型检查都在编译时完成,可以减少运行时的错误。强制类型转换存在安全隐患,比如转换后的类型字节长度变化,发生内存溢出或截断。强类型:每个变量在编译时明确确定,切类型不能改变。支持一些动态类型的功能,如接口和类型断言,原创 2024-03-22 22:44:48 · 454 阅读 · 0 评论 -
【go基础】11.atomic与锁 Mutex, RWMutex
几种锁互斥锁同一时刻只有一个线程可以访问(包含读写)资源问题:加锁失败时,会用阻塞进入内核态,当再次加锁成功,一共会有两次线程切换的成本自旋锁:特殊的互斥锁,在加锁失败时不会使线程进入休眠,而是处于忙等待,让线程在循环中不断检查锁的状态适用:持锁时间短的场景,不会造成线程切换读写锁允许多个线程同时读,但只允许一个线程写适用:可以区分读和写的场景,能提高并发乐观锁:操作数据时认为别人不会修改数据,实现方式——CAS(CompareAndSwap):仅数据是期望值时才修改。原创 2024-03-22 22:35:42 · 808 阅读 · 0 评论 -
【go基础】10.垃圾回收GC
垃圾回收 trace过程Go的GC设计原理。原创 2024-03-22 22:30:32 · 817 阅读 · 0 评论 -
【go基础】9.内存分配, 内存逃逸, 栈空间
概括。原创 2024-03-22 22:18:54 · 987 阅读 · 0 评论 -
【go基础】8.反射reflect
因为 Go 语言的语法元素很少、设计简单,所以它没有特别强的表达能力,但是 Go 语言的 reflect 包能够弥补它在语法上 reflect.Type 的一些劣势。使用反射来调用方法非常复杂,原本只需要一行代码就能完成的工作,现在需要十几行代码才能完成,但这也是在静态语言中使用动态特性需要付出的成本。反射作为一种元编程方式可以减少重复代码,但是过量的使用反射会使我们的程序逻辑变得难以理解并且运行缓慢。interface{}类型的转换需要额外的时间和空间开销,机器码也需要额外的指令来完成类型转换。原创 2024-03-22 22:04:27 · 342 阅读 · 0 评论 -
【go基础】7.context上下文
context是interface{}类型,本质是个指针(interface{}是引用传递),在函数传递过程中会拷贝这个指针,但是context没有暴露直接修改context内容的方法,所以无法修改指针指向的内容。stop是一个用于取消ctx与f关联的function,即如果f还未被触发,stop()可以取消f的注册,若stop()返回值false,说明f已经被触发。在旧版本中done用的chan struct{}类型,现在做了锁优化,atomic.Value是并发安全的,并且可以存储更多种类型的数据。原创 2024-03-22 21:57:06 · 501 阅读 · 0 评论 -
【go基础】6.关键字之for/range, make/new, defer, panic/recover
可以遍历的结构数组/切片map字符串channel- 循环永动机以上代码是不会发生永动的。对于所有的 range 循环,go会在编译期将原切片或者数组赋值给一个新变量,在赋值的过程中就发生了拷贝,又通过 len 关键字预先获取了切片的长度,所以在循环中追加新的元素也不会改变循环执行的次数- 保存range返回变量的地址时,会出现覆盖。原创 2024-03-22 21:45:23 · 665 阅读 · 0 评论 -
【go基础】5.基本数据结构之array, slice, string
策略:如果期望容量大于当前容量的两倍就会使用期望容量;新的字符串是一片新的内存空间,与原来的字符串也没有任何关联,一旦需要拼接的字符串非常大,拷贝带来的性能损失是无法忽略的。当数组中元素所占的字节大小为2/4/8 的倍数时,运行时会对齐内存,将待申请的内存向上取整,提高内存的分配效率并减少碎片。不会拷贝原数组或者原切片中的数据,它只会创建一个指向原数组的切片结构体,所以修改新切片的数据也会修改原切片。go的数组变量代表了整个数组,在传递时传递的是原数组的拷贝,可以理解为一种有序的struct。原创 2024-03-22 21:28:33 · 456 阅读 · 0 评论 -
【go基础】4.基本数据结构之map
而遍历的过程,其实就是按顺序遍历内存地址,同时按顺序遍历内存地址中的 key,但这时已经是无序的了。但也是因为这样,GO设计者加上随机的元素,将遍历 map 的顺序随机化,用来防止使用者用来顺序遍历。(先插入很多元素创建了很桶,但是装载因子达不到6.5的临界值,未触发扩容,之后,删除元素,再插入很多元素,导致创建很多的溢出桶)数组+链表实现,先用哈希函数选择一个桶,遍历桶中的链表,更新或追加键值。反过来,如果是全写,没有读,那么sync.Map还不如加普通map+mutex锁,只有普通map性能的一半;原创 2024-03-22 21:08:14 · 859 阅读 · 0 评论 -
【go基础】3.读channel与select源码
ring buffer环形缓冲区:对于buffered channel,buffer队列是环形队列,有G消费数据时,将队元素取出,下一个元素变为队头,刚刚取出的位置变成队尾。对于接收操作,如果通道中有可用的数据,调度器会唤醒相应的接收goroutine,并将数据从通道的内存复制到接收goroutine的内存中。同样,这个过程也是原子的。以上代码用readyc和advancec的赋值,按轮次处理两个channel,实现了一来一回的通信,readyc向外发一个,advancec就向内接收一个,就很妙。原创 2024-03-22 20:59:51 · 968 阅读 · 0 评论 -
【go基础】2.GMP调度模型
每个P都拥有自己的本地队列,当P上的M执行完当前goroutine后,可以直接从本地队列中取出下一个goroutine来执行,而无需与其他P的队列进行交互。M0:M0是启动程序后的编号为0的主线程,这个M对应的实例会在全局变量runtime.m0中,不需要在heap上分配,M0负责执行初始化操作和启动第一个G, 在之后M0就和其他的M一样了。从缓存区取G的过程,如果本地P为空,从调度器中取P容量的一半个G,放到自己的P里,根据work stealing,偷取的是其他P的一半,所以是否所有P容量相同?原创 2024-03-22 20:43:00 · 575 阅读 · 0 评论 -
【go基础】1.编译器与运行时
它们的运行时既包含运行时环境又包含运行时库,比如JRE里既包含了JVM运行时环境,又包含一整套的Java标准库。在编译阶段,编译器会确定哪些变量应该存储在栈上,以及它们的大小和生命周期,然后生成机器码,这些机器码会指示运行时系统如何执行代码,如何管理栈内存。从线程模型上看:无运行时的语言在线程模型上往往会直接依赖于操作系统,有运行时的Java和C#,往往有自己的一个线程机制,且与系统不一定完全对应。从运行效率上看:无运行时的C/C++运行效率高,有运行时增加了一些负担,不考虑JIT的情况下运行效率会差。原创 2024-03-22 20:26:53 · 620 阅读 · 0 评论