
go
文章平均质量分 74
go语言学习专栏
Achilles.Wang
勿在浮沙筑高台
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
深入理解 Go 中的字节序(Endianness)检测代码
高位字节在前,低位字节在后。如0x0102存储为常见于网络协议(如 TCP/IP)定义一个全局变量,它实现了接口(即支持PutUint16Uint16等方法)。后续将根据系统实际字节序赋值为或。功能说明字节序检测通过读取int16=1的内存布局判断系统字节序接口用于后续的二进制数据操作直接访问内存地址,实现底层判断提供友好的 API 查询当前系统是否为小端。原创 2025-06-11 09:13:44 · 563 阅读 · 0 评论 -
数据库的并发控制
但对于数据库而言,客户端可以以任意顺序获取锁,因此数据库必须检测并解决死锁,这是一个图问题。在乐观并发控制中,事务在冲突时无法继续,这对应用程序来说并不友好,因为它们只能不断重试。涉及I/O操作,我们可以通过在等待I/O时释放锁来进一步优化,以允许其他事务进入,并让只读事务退出。然而,单个写者仍然不足,因为事务的生命周期由客户端控制,可能任意延长。在现实中,这些步骤可以并行运行,因此需要序列化共享的KV结构。这种方法的用处有限,因为写者之间没有并发能力,且长时间运行的事务会导致读者和写者互相阻塞。原创 2025-05-05 22:13:42 · 853 阅读 · 0 评论 -
数据库的原子事务
简单的做法是一次迭代并逐个删除键,但这会将整个表读入内存并在删除前反复更新节点,做了一些无用的工作。在我们的案例中,所有内容使用单一的B+树,我们可以实现一个范围删除操作,无需查看即可释放具有特定范围的所有叶节点。:在任何排序的数据中,邻近的键可能共享一个公共前缀。:写时复制在一次更新中从叶节点到根节点复制节点,这对于多键更新来说不是最优的,因为中间树的节点在一个事务内分配、更新一次然后被删除。另一种方法是通过日志实现原子性,在写时复制树中,更新由根指针捕获,而在原地更新中,则需要日志来捕获更新。原创 2025-05-05 22:11:19 · 963 阅读 · 0 评论 -
数据库的二级索引
行和列作为KV对。范围查询B+树迭代器。保持顺序的编码。二级索引索引选择。需要一个事务性接口。原创 2025-05-05 22:08:43 · 905 阅读 · 0 评论 -
go语言中空结构体
在某些场景下,你并不需要通过通道传递具体的数据,而只是需要一个简单的信号机制来通知其他协程某个事件已经发生。由于空结构体不占用内存,发送和接收空结构体的操作通常比发送和接收复杂数据类型的通道更快。虽然这种差异在大多数情况下是微不足道的,但在高并发或高性能要求的场景下,这些细微的优化可能会产生显著的影响。基于这个特性,在一些特殊的场合之下,可以用做占位符使用,合理的使用空结构体,会减小程序的内存占用空间。空结构体的表象特征,就是没有任何属性,而从更深层次的角度来说,空结构体是一个不占用空间的对象。原创 2025-03-19 10:43:54 · 554 阅读 · 0 评论 -
什么是eBPF?
eBPF(Extended Berkeley Packet Filter)是一种内核技术,允许用户空间程序在不修改内核代码的情况下,通过加载 eBPF 程序来拦截和处理内核事件。这种技术广泛应用于网络过滤、性能分析、安全审计等多种功能。eBPF 作为一种现代操作系统中不可或缺的技术,提供了强大的监控和诊断能力,同时保持了系统的高性能和稳定性。通过其实时数据收集和非侵入式的特性,eBPF 成为了提升系统可观测性的理想选择,推动了操作系统级别的创新和发展。原创 2025-03-04 14:47:28 · 881 阅读 · 0 评论 -
剖析go协程池实现原理
协程本身也是一种资源,但是协程池有自己的特殊性,那是由协程池执行任务的特殊性决定的,协程作为资源使用时其实是在消费其他资源,也就是说必须向协程池提供一个统一的接口,所有需要协程池执行的任务都需要实现该接口,然后被协程池统一调用。触发协程池工作很简单,只需要向协程池等待的通道中放入一个任务即可,当协程池关闭时,所有任务都会被立即执行,当所有任务执行完毕,协程池中的所有协程都会退出。创建协程池需要指定最大并发数,当有新的任务加入时,会立即被执行,而当没有任务时,所有协程池中的协程阻塞竞争等待通道中的"任务"。原创 2024-12-02 15:58:40 · 786 阅读 · 0 评论 -
go语言 Pool实现资源池管理数据库连接资源或其他常用需要共享的资源
Pool用于展示如何使用有缓冲的通道实现资源池,来管理可以在任意数量的goroutine之间共享及独立使用的资源。这种模式在需要共享一组静态资源的情况(如共享数据库连接或者内存缓冲区)下非 常有用。如果goroutine需要从池里得到这些资源中的一个,它可以从池里申请,使用完后归还到资源池里。提到池子,channel天然就是一个池子,而且channel是多线程安全的,所以可以直接使用管道来安全的共享资源。文章按照如下四个方面对Pool资源池的设计过程以及使用进行剖析。原创 2024-12-02 13:52:17 · 683 阅读 · 0 评论 -
go并发设计模式runner模式
真正运行的程序不可能是单线程运行的,go语言中最值得骄傲的就是CSP模型了,可以说go语言是CSP模型的实现。原创 2024-12-01 13:28:12 · 1456 阅读 · 0 评论 -
go语言切片
还可以通过对切片再次切片来缩小一个切片的大小。空切片和nil切片并不等价,空切片和nil切片是不同的。空切片是一个长度为0,容量为0的切片,而nil切片是一个未初始化的切片,它指向一个不存在的内存区域。操作超过当前切片的容量时,Go 会分配一个新的更大的底层数组,并将原有数据复制到新的数组中。当使用make指定的切片长度为0时,那么底层其实会创建一个指针指向zerobase的切片,这时的Data指向。和C++的vector一样,在进行扩容时,一般会大于实际需要的长度,在实际使用中能有效的减少扩容的次数。原创 2024-11-29 17:41:49 · 1289 阅读 · 0 评论 -
go结构体匿名“继承“方法冲突时继承优先顺序
在 Go 语言中,当一个结构体匿名嵌入了多个实现相同接口的结构体时,调用该接口方法时会优先选择自己实现的方法,如果自己没有实现该方法,就按照顺序从上到下找到第一个定义的方法。方法的定义顺序决定了调用哪个方法。但是为了避免歧义和提高代码的可读性,建议在设计时尽量避免这种情况,或者在外部结构体中显式地实现接口方法。原创 2024-11-28 10:22:52 · 499 阅读 · 0 评论 -
go语言range的高级用法-使用range来接收通道里面的数据
在 Go 语言中,可以使用循环来遍历通道(channel)。循环会一直从通道中接收值,直到通道关闭并且所有值都被接收完毕。原创 2024-11-22 10:06:35 · 1151 阅读 · 0 评论 -
go语言闭包捕获的是变量的引用而不是变量的值
在 Go 语言中,闭包捕获的是变量的引用,而不是变量的值。这意味着闭包会引用变量的实际内存位置,而不是在闭包创建时复制变量的值。为了避免在循环中创建多个闭包时出现意外的结果,可以使用匿名函数参数或将循环变量赋值给一个新的局部变量,确保每个 goroutine 捕获的是不同的变量。这两种方法都可以有效解决这个问题,确保每个 goroutine 打印出预期的值。原创 2024-11-21 15:08:36 · 620 阅读 · 0 评论 -
线段树segment_tree go语言实现
线段树(segment tree)什么是线段树线段树是一种二叉搜索树,什么叫做二叉搜索树,首先满足二叉树,每个结点度小于等于二,即每个结点最多有两颗子树,何为搜索,我们要知道,线段树的每个结点都存储了一个区间,也可以理解成一个线段,而搜索,就是在这些线段上进行搜索操作得到你想要的答案。线段树是建立在线段的基础上,每个结点都代表了一条线段[a,b]。长度为1的线段称为元线段。非元线段都有两个子结点,左结点代表的线段为[a,(a + b) / 2],右结点代表的线段为[((a + b) / 2)+1,b]原创 2022-03-11 22:29:22 · 932 阅读 · 1 评论 -
Go Embed简明教程
Go Embed简明教程go语言程序都是编译成二进制可执行文件的,但是实际执行时除了需要可执行程序,还需要一些静态文件,比如html模板等,于是就有人想如果Go官方能内建支持就好了。2019末一个提案被提出 issue#35950,期望Go官方编译器支持嵌入静态文件。后来Russ Cox专门写了一个设计文档 Go command support for embedded static assets, 并最终实现了它。需要注意的这个功能在go 1.16beta之后才支持对于单个的文件,支持嵌入为原创 2021-09-26 21:47:00 · 2673 阅读 · 0 评论 -
使用go语言GUI库实现对mp3文件的播放1(简单的播放mp3文件)
使用go语言GUI库实现对mp3文件的播放1(简单的播放mp3文件)使用beep播放mp3文件(10num)使用go语言GUI库fyne实现音乐播放器要是想使用go语言实现播放mp3需要借助beep库,在github上有已经开源的库路径如下:beep库文件路径下面的代码只是实现了简单的播放功能,没有暂停和快进的功能package mainimport ( "github.com/faiface/beep" "github.com/faiface/beep/mp3" "gi原创 2021-08-25 22:25:36 · 2172 阅读 · 0 评论 -
使用go语言GUI库fyne绘制一个交通标志
绘制一个交通标志首先实现一个函数makeSign(),该函数返回fyne.CanvasObject对象,对象中实现所有的图形func makeSign() fyne.CanvasObject { bg := canvas.NewCircle(color.NRGBA{R: 255, A: 255}) bg.StrokeColor = color.White bg.StrokeWidth = 5 bar := canvas.NewRectangle(color.White)原创 2021-08-24 23:28:38 · 679 阅读 · 0 评论 -
golang的GUI库,使用go-fyne设计一个代办事项APP
Designing task list我们在这一节中将会设计一个,左边是列表,右边列表中代办事项的具体内容实现效果如图:实现该需要使用总共用了两个文件,一个task_list.gopackage mainimport ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/app" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" "ti原创 2021-08-16 23:12:37 · 2393 阅读 · 0 评论 -
使用fyne绘制一个交通图标
fyne绘制一个交通标志首先实现一个函数makeSign(),该函数返回fyne.CanvasObject对象,对象中实现所有的图形func makeSign() fyne.CanvasObject { bg := canvas.NewCircle(color.NRGBA{R: 255, A: 255}) bg.StrokeColor = color.White bg.StrokeWidth = 5 bar := canvas.NewRectangle(color.Whi原创 2021-07-13 23:23:30 · 797 阅读 · 0 评论 -
go语言goroutine的取消
go语言中使用 contex实现goroutine的取消package mainimport ( "context" "fmt" "sync" "time")// context 如何优雅的控制子goroutinevar wg sync.WaitGroupfunc f(ctx context.Context) { defer wg.Done() //整个缩进都会跳出LOOP: for { fmt.Println("child goroutine") time.Sl原创 2021-02-05 23:16:47 · 364 阅读 · 0 评论 -
go性能优化
Go性能优化CPU profile:报告程序CPU使用情况,按照一定频率去采集应用程序CPU和寄存器上面的数据Memory Profile (Heap Profile):报告内存使用情况Block Profiling:报告goroutines不在运行状况情况下,可以用来分析和查找死锁等性能瓶颈Goroutine Profiling:报告goroutine的使用情况,有哪些goroutine它们调用关系是怎样的package mainimport ( "flag" "fmt" "os"原创 2020-12-22 23:27:06 · 445 阅读 · 0 评论 -
go get 命令提示没有权限问题解决
出现一下类似的问题,是因为你安装go是直接将go源码解压进行安装的,需要对解压后的go目录加上可执行权限:go get github.com/google/pprof: copying /tmp/go-build384767642/b001/exe/a.out: open /usr/local/go/bin/pprof: permission denied家可执行权限:#进入到对应目录,执行:sudo chmod -R 777 go/...原创 2020-12-22 00:07:01 · 2933 阅读 · 0 评论 -
go语言中的闭包
闭包闭包是什么?闭包是一个函数,这个函数包含了他外部作用域的变量函数可以作为返回值函数内部查找变量的顺序,先自己内部找,找不到再往外层找如何形成闭包结构内层函数+外层函数局部变量(可以是入参或者定义的局部变量) = 闭包结构如果将一个内层函数作为函数返回值内层函数中又涉及到外层函数的局部变量(自己定义或者外部传进来的参数,都是局部变量)1+2 条件满足后,就会导致该局部变量的声明周期发生改变,外层函数的局部变量不会随着外层函数的借宿而销毁将这种内层函数变量和外层局部变量,统称为闭包结构原创 2020-12-14 22:25:31 · 266 阅读 · 0 评论 -
go语言中goroutine池
创建三个goroutine,创建5个任务,用三个goroutine干5个任务package mainimport ( "fmt" "time")func worker(id int, jobs <-chan int, results chan<- int) { for j := range jobs { fmt.Printf("worker:%d start job:%d\n", id, j) time.Sleep(time.Second) fmt.Printf("原创 2020-12-12 20:29:13 · 305 阅读 · 0 评论 -
go语言中的匿名函数
匿名函数:没有名字的函数package mainimport "fmt"func main() { /* 匿名函数: 没有名字的函数 匿名函数,需要在匿名函数尾部加上()直接调用 */ func1() // 匿名函数采用的也是函数名字 ()实现调用 // 匿名函数的实现和调用 func() { fmt.Println("Anonymous call back.") }() // 加上了小括号实现了函数的调用 // 匿名函数的多次调用 func3 := fu原创 2020-12-10 23:51:14 · 415 阅读 · 0 评论 -
go语言中处处可见的for循环
package mainimport ( "fmt" "math")type xPoint struct { name string age int}// 结构体比较大的时候尽量使用指针的类型 进行构造函数// go语言中 构造函数都是以new开头的func newPoint(name string, age int) *xPoint { return &xPoint{ name: name, age: age, }}func main() {原创 2020-12-10 00:22:30 · 176 阅读 · 0 评论 -
go语言中错误的处理和实现自己的错误处理类型
package mainimport ( "errors" "fmt")func main() { /* 错误:在可能出现问题的地方出现问题, 如打开一个文件打开失败是意料之中的事情 异常:在不该出现错误的地方出现错误, 如出现空指针,意料之外的情况 */ //exec.Command("pwd") //exec.Command("ps") //f, err := os.Open("test.txt") //if err != nil { // log.Fatal(er原创 2020-12-10 00:21:00 · 286 阅读 · 0 评论 -
go语言中使用递归函数实现文件目录的遍历
实现思路:使用ioutil.ReadDir将当前文件信息都读取完,并对目录进行遍历,当当前目录遍历时,如果发现某个文件是子文件夹,就使用回调,再对子目录调用ioutil.ReadDir读取所有的文件信息,以此进行实现将当前文件夹下所有的文件进行遍历package mainimport ( "fmt" "io/ioutil" "log")func main() { // listFiles(".", 0)}func listFiles(dirName string, level原创 2020-12-10 00:07:09 · 499 阅读 · 0 评论 -
go语言中的defer
defer的词义: 延迟 推迟在go语言中,使用defer关键字来延迟一个函数或者方法的执行1. defer 函数或方法 一个函数或方法会被延迟执行2. defer的使用A 对象文件的close 临时文件的删除B go语言中关于异常的处理,使用panic 和recoverpanic函数引发的恐慌 导致程序中断执行recover函数用于恢复程序的执行recover()语法上要求必须在defer中执行3. 如果多个defer函数倒序调用 最后defer调用的最先被调用package main原创 2020-12-10 00:00:16 · 565 阅读 · 0 评论 -
go语言中channel的创建和销毁以及匿名函数的使用
channel的创建go语言中,任意类型前面加上关键字chan即可声明对应类型的通道,创建通道需要使用make,make也用于map 和slice的创建创建一个通道/*刚创建的通道是nil*/var a chan boola = make(chan bool)使用匿名函数创建一个goroutinego func() { for i := 1; i < 10; i++ { fmt.Println("子goroutine is running....", i) } // 往通道中原创 2020-12-09 23:58:07 · 1024 阅读 · 0 评论 -
go语言buffio与继承
buffio比较简单,主要就是对Io一类的操作,第一个例子中顺带加上了go语言中继承的实现,因为go不是面相对象的语言,更准确的来说是面相接口编程的语言,因此继承的实现其实就是将另外一个结构体合并到自己的结构体中,package mainimport ( "bufio" "fmt" "os")type animal struct { eye int foot int}type dog struct { animal // 对animal实现继承 watch string原创 2020-12-09 23:43:29 · 349 阅读 · 0 评论 -
go语言中变量的定义和使用
Go语言是静态类型语言,因此变量(variable)是有明确类型的,编译器也会检查变量类型的正确性。在数学概念中,变量表示没有固定值且可改变的数。但从计算机系统实现角度来看,变量是一段或多段用来存储数据的内存。声明变量的一般形式是使用 var 关键字:var name type其中,var 是声明变量的关键字,name 是变量名,type 是变量的类型。需要注意的是,Go语言和许多编程语言不同,它在声明变量时将变量的类型放在变量的名称之后。这样做的好处就是可以避免像C语言中那样含糊不清的声明形式,原创 2020-12-09 23:26:31 · 866 阅读 · 0 评论 -
go语言数组的使用
go语言的数组除了和C语言的定义时方式不同,使用起来基本上是一样的定义数组://定义一个类型为 [4]int类型的数组var arrName [4]intarrName[0] = 1 // 对数组进行赋值,可以看到,索引还是从0开始的,和C语言保持了一致var arrname2 = [4]int{1, 2, 3, 4} // 创建一个数组并对其进行初始化var b = [5]int{1, 2, 3} // [5]int 类型的数组,只初始化3个值var c = [5]int{1: 1, 3:原创 2020-12-09 23:14:44 · 313 阅读 · 0 评论 -
go语言中结构体与json
go语言中使用Marshal函数实现结构体json化,需要有一下两点注意因为json化是在其他函数中完成,因此需要将结构体中的成员大写,这样才能在生成的结构体中有对应的元素在结构体后面,如果有需要改写字段名称,需要使用烦引号,指定对应的字段名称,支持多指定如json:"name" db:"dbname",这样在不同函数调用的时候,就会生成不同的键值对package mainimport ( "encoding/json" "fmt")// json -- struct// 注原创 2020-12-07 00:09:26 · 1332 阅读 · 0 评论 -
go语言游戏编程-Ebiten使用矩阵实现对图的缩放和移动
如何使用矩阵绘图这个程序几乎和渲染一个图片一模一样,唯一一点不同的是,增加了option参数,并依靠参数,实现了对图像的放大和移动package mainimport ( "github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten/ebitenutil" _ "image/png" "log")var mImg *ebiten.Imagefunc init() { var err error mImg, _, e原创 2020-12-04 00:32:58 · 588 阅读 · 0 评论 -
go语言游戏编程-Ebiten渲染一张图片
渲染一个图片完整实现代码:package mainimport ( "fmt" "github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten/ebitenutil" _ "image/png" "log")var img *ebiten.Imagefunc init() { var err error img, _, err = ebitenutil.NewImageFromFile("gopher.png")原创 2020-12-04 00:30:28 · 703 阅读 · 0 评论 -
go语言游戏编程-Ebiten实现画面的填充
Draw完整代码如下:package mainimport ( "github.com/hajimehoshi/ebiten" "image/color" "log")type fGame struct {}func (g *fGame) Update() error { return nil}func (g *fGame) Draw(screen *ebiten.Image) { screen.Fill(color.RGBA{R: 0xff, A: 0xff})}原创 2020-12-02 23:36:33 · 572 阅读 · 0 评论 -
go语言游戏编程初识--`Ebiten`
Ebitenebiten是一个简单的使用纯go实现的游戏,使用这个库即可以实现go语言代码的学习,又可以实现对游戏编程的了解。Hello world让我们以一个Hello world!开始ebiten的学习,完整代码实现如下:package mainimport ( "github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten/ebitenutil" "log")type Game struct {}func (原创 2020-12-02 23:15:19 · 2246 阅读 · 0 评论 -
Go语言的并发模型
Go语言的并发模型Go 语言相比Java等一个很大的优势就是可以方便地编写并发程序。Go 语言内置了 goroutine 机制,使用goroutine可以快速地开发并发程序, 更好的利用多核处理器资源。接下来我们来了解一下Go语言的并发原理。一、线程模型在现代操作系统中,线程是处理器调度和分配的基本单位,进程则作为资源拥有的基本单位。每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成。线程是进程内部的一个执行单元。 每一个进程至少有一个主执行线程,它无需由用户去主动创建,是由系统自动创建原创 2020-11-01 18:51:05 · 331 阅读 · 0 评论 -
go语言中的闭包结构
每次调用 increment都会重新生成一个闭包结构中的变量内层函数+外层函数局部变量(可以是入参或者定义的局部变量) = 闭包结构如果将一个内层函数作为函数返回值内层函数中又涉及到外层函数的局部变量(自己定义或者外部传进来的参数,都是局部变量)1+2 条件满足后,就会导致该局部变量的声明周期发生改变,外层函数的局部变量不会随着外层函数的借宿而销毁这种内层函数变量和外层局部变量,统称为闭包结构闭包结构中,局部变量的声明周期会发生改变package mainimport "fmt"f原创 2020-10-25 19:53:40 · 306 阅读 · 0 评论