我们在使用Go标准库以及一些第三方库时,经常看到需要传入一个context.Context
类型的参数。Context 一词翻译过来叫做“上下文”,但在Go语言中,它到底有什么用,应该怎样用呢?
如何停止线程/协程?
我们就以之前聊到的 五子棋AI 为例:
假设我们计算6步棋花了数秒钟,但是计算8步棋花了1分钟还没算出来,就可以提前返回计算6步的策略了。
这段话看似简单,实则涉及到并发编程的一个问题:提前返回后,8步棋的计算仍在进行,这样会持续浪费资源,如何将其停掉呢?
我们在使用Go标准库以及一些第三方库时,经常看到需要传入一个context.Context
类型的参数。Context 一词翻译过来叫做“上下文”,但在Go语言中,它到底有什么用,应该怎样用呢?
我们就以之前聊到的 五子棋AI 为例:
假设我们计算6步棋花了数秒钟,但是计算8步棋花了1分钟还没算出来,就可以提前返回计算6步的策略了。
这段话看似简单,实则涉及到并发编程的一个问题:提前返回后,8步棋的计算仍在进行,这样会持续浪费资源,如何将其停掉呢?
在Go语言中,尽管许多panic
可以通过recover()
函数来捕获并处理,但依然存在一些特定情况下引发的异常是无法被捕获的。本文将探讨几种常见的无法通过常规手段恢复的错误情形及其原因。
map
当尝试同时从多个协程读取和修改同一个map
时,如果没有适当的同步机制(如使用互斥锁),则会触发运行时错误。
m := make(map[int]int)
go func() { for { m[1] = 1 } }()
go func() { for { _ = m[1] } }()
假设某个游戏,已知各个角色的总胜率为 r总,出场率为 p总。在高分段的对局中,总胜率和出场率分别为 r高 和 p高。如果我们想要反向推导出所有角色在低分段的胜率和出场率 r低 和 p低,可以这样推导:
select
语句awk
是Linux中处理文本文件的语言,功能非常强大。
awk options 'pattern { action }' file
其中,options
是一系列可选参数,我们最常用的是-F
参数,用于指定分隔符,例如-F ','
表示以,
为分隔符,如果不指定则默认是空格。'pattern { action }'
是脚本的内容,其中pattern
是个布尔表达式,满足这个表达式的行才会被输出,默认是遍历所有行。file
是要处理的文件。
在 Git 中,git revert -m
命令中的 -m
选项(全称 --mainline
)用于指定撤销合并提交时要保留的主线分支。这个选项仅在撤销合并提交(merge commit)时需要用到。
我们在使用 Redis 时,对 List 数据结构的操作经常使用的是 LPUSH
、RPUSH
、LPOP
、RPOP
等命令,这些命令都是非阻塞的。
Redis 还提供了对 List 数据结构的阻塞操作 BLPOP
和 BRPOP
。
命令格式是:
BLPOP LIST1 LIST2 .. LISTN TIMEOUT
从 Go 1.11 开始,Go 引入了模块化管理,并于 Go 1.16 版本开始正式成为默认构建模式。现在,Go 模块已经成为 Go 语言通用的包管理方式。
在项目根目录下使用go mod init example/mymodule
就可以初始化一个 Go 模块,并生成一个名为 go.mod 的文件,其中第一行即为module example.com/mymodule
。
go.mod 文件用于描述模块的依赖关系和版本信息。一个可能的 go.mod 文件可以包含以下内容:
整理了一下我用过的 Go 开源第三方库,供大家参考。使用时请注意遵守各个库的开源协议。
golangci-lint是一个Go语言的代码静态检查工具集,官网是https://golangci-lint.run/,它集成了多个流行的linters,可以帮助我们快速发现代码中的潜在问题。