自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(27)
  • 收藏
  • 关注

原创 Go内存管理(下)

在每个P中都有一个pageCache类型的字段pcache,我们称为页的缓存。就是它保存了一组等待被使用的连续的页。对于要分配的的page数小于16个page的内存,我们都会先从pcache中查找是否有空闲的空间可供分配,pageCache结构体被用于实现P(处理器)的本地内存页缓存,这种结构体的设计有助于提高内存分配的效率和性能,特别是在多线程或并发环境下。结合pageCache的结构定义,base表示这一组连续页的起始地址,cache是一个uint64对象,在64位机器上是8个字节,即64个bit。

2024-01-31 17:13:43 871 1

原创 Go内存管理(上)

在进入本章内容学习之前,最好能够对虚拟内存以及一些基本的物理内存知识有一定了解,这样能帮助更好的深入理解一些概念。为了缩减内容篇幅,聚焦重点内容,就不一一去讲解了,这边提供几个相关内容的参考地址,如下:虚拟内存知识可以参考该地址: https://blog.csdn.net/qqxjx/article/details/133852071物理内存知识可以参考该地址:https://blog.csdn.net/qqxjx/article/details/134119042。

2023-12-19 17:02:38 947

原创 GO调度模型-GMP(下)

集齐各部分理论碎片之后,我们可以尝试对 的宏观调度流程进行整体串联,开始进入到调度函数, 此时的执行权位于 手中:分析代码,我们去掉一些非关键的逻辑和问题,总结起来该函数流程就两个:下面对这两个函数进行重点分析。调度流程中,一个非常核心的步骤,就是为 寻找到下一个执行的 ,这部分内容位于函数 方法中,该函数非常冗长,为了寻找一个可用的,真是用心良苦,我们看下源码分析:综合代码,来总结下流程:总结起来就是各种办法找,到最后还不死心,在能找的地方再找一次。其流程图如下:下面来根据 函数,来看看调度

2023-11-28 17:22:02 560

原创 GO调度模型-GMP(上)

首先我们要先了解g0和m0,首先要了解什么是g0和m0g0 g可以看出m0和g0都是全局变量,分别对应着m结构体和g结构体, 但是他们和普通的g和m还是有着区别的。m0启动程序后的编号为0的主线程,如果进程中不开任何线程,可以理解为一个进程就是一个线程;定义在全局变量runtime.m0中,不需要在heap(堆)上分配;负责执行初始化操作和启动第一个gg0启动第一个g之后,m0就和其他的m一样了( 负责给其他m进行抢占 )。每次启动一个m,都会第一个创建的goroutine,就是g0g0。

2023-11-15 10:39:53 336

原创 Linux - 物理内存

在虚拟内存文章中,我们知道进程的虚拟内存布局以及相关知识。为了能够承上启下,我们下面从计算机组成原理的角度介绍物理内存的相关概念,以便后续能够将虚拟内存与物理内存知识进行关联串联,使自己更深入的了解内存管理相关知识点,最后对的内存管理进行解析。内核是以页()为基本单位对物理内存进行管理的,内核将整个物理内存按照页对齐方式划分成千上万个页()进行管理,每页大小为 。系统中每个都是的一个实例,那么针对一个内存,那么将会存在上百万个结构。 中封装了每页内存块的状态信息,比如:组织结构,使用信息,统计信息,以及与其

2023-10-30 14:43:06 1472

原创 Linux - 虚拟内存

在没有虚拟内存概念的时候(DOS时代),程序寻址用的都是(实际存在硬件里面的空间地址,程序能寻址的范围是有限的,这取决于CPU的地址线条数。比如在32位平台下,寻址的范围是2^32^也就是4G。并且这是固定的,如果没有虚拟内存,且每次开启一个进程都给4G的物理内存,就可能会出现很多问题:因为物理内存时有限的,当有多个进程要执行的时候,都要给4G内存,很显然你内存小一点,这很快就分配完了,于是没有得到分配资源的进程就只能等待。当一个进程执行完了以后,再将等待的进程装入内存。

2023-10-16 09:51:01 433

原创 Go同步原语之sync/Pool

Pool本质是为了提高临时对象的复用率;Pool使用两层回收策略(localvictim)避免性能波动;Pool本质是一个杂货铺属性,啥都可以放。把什么东西放进去,预期从里面拿出什么类型的东西都需要业务使用方把控,Pool池本身不做限制;Pool池里面cache对象也是分层的,一层层的cache,取用方式从最热的数据到最冷的数据递进;Pool是并发安全的,但是内部是无锁结构,原理是对每个P都分配cache数组(数组),这样cache结构就不会导致并发;永远不要copy一个Pool。

2023-09-15 11:06:36 207 2

原创 Go同步原语之sync/Map

在结构体内容部分介绍过,entry.p是一个nilexpunged、其他正常值。那nilexpunged有啥区别呢?其实nilexpunged都用来表示keynilread map和dirty map在物理上仍保有该key-entry对,因此倘若此时需要对该entry执行写操作,可以直接CAS操作;expungeddirty map中已经没有该key-entry对,倘若执行写操作,必须加锁(dirty map必须含有全量key-entry对数据);设计expunged和nil。

2023-09-06 17:22:58 108 1

原创 Go同步原语之sync/Once

方法传入的函数中再次调用方法会有什么问题吗?})})通过分析sync.Once的源码,可以看到它包含一个名为m的互斥锁字段。当我们在Do方法内部重复调用Do方法时,将会多次尝试获取相同的锁。但是mutex互斥锁并不支持可重入操作,因此这将导致死锁现象。方法中传入的函数发生了panic,重复传入还会执行吗?err!= nil{})}()})在执行的过程中如果f出现panic,后面也不会再执行了;所以不会打印任何东西,方法中传入的函数只会被执行一次,哪怕函数中发生了panic;

2023-09-04 11:39:49 71 2

原创 Go同步原语之sync/waitGroup ---- 等待组

WaitGroup可以用于一个goroutine等待多个goroutine干活完成,也可以多个goroutine等待一个goroutine干活完成,是一个多对多的关系Add(n>0)方法应该在启动goroutine之前调用,然后在goroution内部调用Done方法WaitGroup必须在Wait方法返回之后才能再次使用Done只是Add的简单封装,所以实际上是可以通过一次加一个比较大的值减少调用,或者达到快速唤醒的目的。

2023-09-01 11:00:38 282 2

原创 Go同步原语之sync/mutex ---- 互斥锁

Mutex(互斥锁)是一种用于多线程编程的同步机制。它是""(互斥)的缩写,用于控制多个线程对共享资源的访问,以避免出现并发访问引起的问题,如数据竞争(Data Race)和不一致性。在多线程环境中,多个线程可以并发地访问共享资源,例如共享变量、数据结构或文件等。如果没有适当的同步机制,多个线程可能会同时修改同一份数据,导致不可预测的结果或者程序错误。使用互斥锁可以确保在任意时刻只有一个线程能够获得锁,从而访问共享资源。当一个线程获得了互斥锁,其他试图获得锁的线程会被阻塞,直到持有锁的线程释放锁。

2023-08-30 17:51:59 272 1

原创 Protocol Buffers编码

在对ProtoBuf做了一些基本介绍之后,这篇开始进入正题,深入ProtoBuf的一些原理。我们都知道采取了二进制编码结构传输,但其二进制编码相比普通的二进制编码更加紧凑,旨在高效地序列化和传输结构化数据。这种编码结构与XML或JSON相比更加紧凑,因为它不包含标签名称和其他冗余信息,仅关注数据的有效表示。在将其数据转化为其二进制编码的过程中采取了多种编码方式协同,主要采用了TLVVarintFixed32Fixed64和等编码方式。

2023-08-23 17:23:27 55

原创 Protocol Buffers基础

在中,service用于定义RPC)服务。RPC服务定义了一组可以通过网络进行调用的方法,这允许不同的应用程序在不同的计算机上进行通信。以下是service在protobuf// 可以定义更多的 rpc 方法...在上述语法中,是你定义的服务名称,MethodName是你定义的RPC方法名称,是该方法接收的请求消息类型,是该方法返回的响应消息类型。以下是一个示例,展示了如何在proto文件中定义一个简单的RPC在上述示例中,我们定义了一个名为的服务,其中包含一个名为Add的RPC方法。

2023-08-15 17:34:15 82 1

原创 Go语言基础知识点 —— Memory Alignment 内存对齐

为了更好的了解内存对齐概念,我们先要了解下内存的一些物理结构以及CPU和内存之间数据交互基础知识,一般内存的外形图片如下:一个内存是由若干个黑色的内存颗粒构成,每一个黑色的内存颗粒叫做一个chip,市面上大多数内存条都有8个chip,而每个chip拥有8张二维矩阵bankbank是由一个个的存储单元组成的矩阵,每个cell存储一个(8个小电容)数据 ,bank的每一行就叫做一个,每一列叫做一个,通过colum和row可以定位一个cell。cell示意图:了解完大概的内存结构后,我们来了解CPU。

2023-07-26 16:30:02 109 1

原创 Go语言基础知识点 —— Closure 闭包

闭包是函数值和引用环境的组合。闭包可以捕获包含它的函数作用域内的变量。闭包可以在函数结束后继续访问和修改捕获的变量。每次调用函数时都会创建一个新的闭包实例,每个闭包实例都有自己的引用环境和捕获的变量。闭包可以用于实现状态的保持和共享,尤其在并发编程中很有用。闭包的生命周期可能会比函数长,因为它可以在函数结束后仍然被其他部分引用和使用。使用闭包时要注意避免出现不必要的内存泄漏,确保在不需要时释放对捕获变量的引用。闭包在Go语言中被广泛使用,可以帮助我们编写更灵活和功能强大的代码。

2023-07-25 17:16:20 107 1

原创 Go语言基础结构 —— Channel 通道

在Go语言中,channel(通道)是一种用于在goroutine之间进行通信和同步的特殊数据结构。它可以看作是一条管道,可以在不同的goroutine之间传递数据。使用通道,你可以在goroutine之间发送和接收值。通道提供了一种安全、同步的方式来共享数据。它确保在发送操作完成之前,接收操作会一直等待,并且在接收操作完成之前,发送操作也会一直等待。这种同步机制可以有效地避免并发访问共享数据时出现的竞争条件和数据竞争。Golang并发的核心哲学是不要通过共享内存进行通信。

2023-06-25 11:56:27 1411

原创 Go语言基础结构 —— Interface 接口

接口是Go语言编程中数据类型的关键。在Go语言的实际编程中,几乎所有的数据结构都围绕接口展开,接口是Go语言中所有数据结构的核心。Go语言中的接口实际上是一组方法的集合,接口和gomock配合使用可以使得我们写出易于测试的代码.但是除了在反射等使用场景中我们很难直接感知到接口的存在(虽然大多数人使用反射的时候也没有感知到接口在其中发挥的作用),但是想要深入理解Go语言,我们必须对接口有足够的了解.接下来我们将从接口的数据结构、结构体如何转变成interface和Go语言中动态派发的实现这些方面来一起学习。

2023-06-15 17:33:08 2017

原创 Go语言基础结构 —— func 函数

在Go语言中,使用func关键字来定义函数。// 函数体 }其中:函数声明:关键字func代表是函数的名称,函数名由字母、数字、下划线组成。但函数名的第一个字母不能是数字。在同一个包内,函数名称不能重名。parameter1和parameter2代表是函数的参数,type是参数的类型。参数由参数变量和参数变量的类型组成,参数变量可以省略,可以有一个参数,也可以有多个,也可以没有;多个参数之间使用分隔;多个参数时参数变量要么全写,要么全省略;

2023-06-09 16:35:22 1885

原创 Go语言基础结构 —— Map 哈希表

来看一个例子, 给定一个数组数据:, 求该组数据中是否有元素100O(N)BSTO(log N)那么有没有一种方法使查找效率更高呢?我们的一种思路是这样的:创建一个以数组最大值作为长度的的数组temp;以原数组中值作为数组temp的键值最后查找哪个元素是否存在就直接返回temp数组中该索引下标位置即可这边我们巧妙借助了数组的索引下标,直接返回某元素对应的索引下标值即可,于是我们想到构造一种存储结构,使,这样依据存储位置直接便查找到了该元素。这就是哈希表(hashmap)的最原始思路。

2023-05-24 09:21:42 322

原创 Go语言基础结构 —— Slice 切片

在Go语言中,切片(Slice)是一种数据结构,它是对数组一个连续片段的引用,这个数组称为切片的底层数组。切片和数组的关系是非常紧密的。在Go语言中,数组是一个固定长度的序列,而切片则是一个可变长度的序列。切片是建立在数组之上的,它提供了动态数组的功能,可以根据需要动态地增加或缩小切片的长度。

2023-05-15 10:22:53 1322

原创 Go语言基础结构 —— Array 数组

数组是go语言中的特殊类型,其与其他语言不太一样。他不可以添加,但是可以获取值,获取长度。数组的拷贝都是值拷贝,因此不要尽量不要进行大数组的拷贝。常量的下标以及某一些变量的下标的访问越界问题可以在编译时检测到,但是变量的下标的数组越界问题只会在运行时报错。数组的声明中,存在一个语法糖。,但是本质本没有什么差别在编译期的优化阶段,还会进行重要的优化。当数组的长度小于4时,在运行时会在栈中进行初始化。当数组的长度大于4,会在静态区初始化数组其实我们在go。

2023-05-08 09:58:08 798

原创 Go语言基础结构 —— String 字符串

比特(bit)是计算机处理的最小单位,值为0或者1,一个字节包含8个bit,最大值(11111111)为255,最小值(00000000)为0;一个字节能代表256个数字,二个字节可以表示65563个数字,更多的字节可以有更多种组合,就可以表示更大的数值范围,整数可以这样存,那么字符呢?一堆二进制0或者1,无论怎么也算不出A,那就通过数字中转一下,只要给A指定一个数值编号,要存储A。

2023-04-23 16:27:05 992

原创 上下文-Context

Golanggoroutine,它是有Golang在Golang中,我们无法从外部终止一个协程,只能它自己结束。常见的比如超时取消等需求,我们通常使用抢占操作或者中断后续操作。在Context出来以前,Golang是的方式来做这件事情的。具体的做法是:定义一个channel,子协程启一个定时任务循环监听这个channel,主协程如果想取消子协程,就往channel里写入信号。这时我们需要一种优雅的方案来实现这样一种机制,Context就派上用场了。

2023-04-18 18:30:35 186

原创 Go语言标准库之net/http(四) —— Server

golang net/http server

2023-04-18 10:45:43 470 1

原创 Go语言标准库之net/http(三) —— Client

一般情况下,我们并不需要自定义来控制控制HTTP请求的行为和配置,使用net/http包中默认的即可,在client.go可以看出默认的并没有设置Client任何属性值,但是如果我们需要设置HTTP请求的超时时间、代理、连接池等选项,可能就需要我们自己去定义和创建了。根据Client结构体内容,我们知道拥有TransportJarTimeout四个属性字段,详细介绍如下:Timeout它用于设置HTTP客户端的超时时间,是一个类型的值,表示客户端在发送请求后等待服务器响应的最大时间。

2023-04-05 22:13:44 1316

原创 Go语言标准库之net/http(二) —— Response

HTTP响应头部包含一组属性-值对,用于描述HTTP响应的各种属性,例如响应的内容类型、长度、缓存控制等。同上, 状态码原因是跟状态码一一对应的,可以参考: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status。它们被用于描述服务器的基本信息,以及数据的描述,服务器通过这些数据的描述信息,可以通知客户端如何处理等一会儿它回送的数据。响应体的内容可以是静态的文件,也可以是动态生成的内容,例如通过。响应的一部分,包含服务器返回给客户端的数据。

2023-04-05 22:07:28 634 1

原创 Go语言标准库之net/http(一) —— Request

Http协议(Hyper Text Transfer Protocol,超文本传输协议)是一个简单的请求-响应协议,它通常运行在TCP之上。Http协议是基于客户端(Cilent)/服务器(Server)模式,且面向连接的。简单的来说就是客户端(Cilent)向服务器(Server)发送http请求(Request),服务器(Server)接收到http服务请求(Request)后会在http响应(Response)中回送所请求的数据。Go的标准库net/http则提供了对http。

2023-04-05 21:57:14 747

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除