Recommended Go Packages

以下是推荐的软件包,它们在生产环境下表现不错 Package Comment Repository fasthttp 高性能 HTTP 服务器和客户端 https://github.com/valyala/fasthttp fasttemplate 高性能字符串替换 https://github.com/valyala/fasttemplate fastjson 高性能 JSON 解析 https://github.com/valyala/fastjson qucktemplate 高性能序列化到 HTML/JSON/XML https://github.com/valyala/quicktemplate tableflip 热升级 https://github.com/cloudflare/tableflip UUID Google 的项目 https://github.com/google/uuid structure 推荐的文件目录结构 https://github.com/golang-standards/project-layout godotenv 环境变量 https://github.com/joho/godotenv sqlx 数据库工具 https://github.com/jmoiron/sqlx

October 1, 2022 · 1 min · Kehan Pan

Golang Rand Concurrency Safe

Golang 提供标准随机包 math/rand,随机包默认会创建一个全局的对象,从源码上可以看到使用了 lockedSource 这个源,并且是基于 1 创建的 Source,也就是说每次初始化都是固定的结果,这一点和 C 一样。 var globalRand = New(&lockedSource{src: NewSource(1).(*rngSource)}) // Type assert that globalRand's source is a lockedSource whose src is a *rngSource. var _ *rngSource = globalRand.src.(*lockedSource).src 在项目中为了增加随机性,比较常见的做法是每次程序启动时都把全局的随机对象重新设置一下,比如用当前时间作为随机种子,这一切看起来都非常美好,直到某个比较有想法的包出现。 import ( "math/rand" "time" ) func init() { rand.Seed(time.Now().UnixNano()) } 现在试想一下需要开发一个独立的包,基于某些原因它需要使用随机数,自然而然的想到 math/rand 包,但是基于解耦和随机安全的考虑,肯定是不能使用系统自带的全局随机对象,因为无法保证它有没有被好好设置,也不太好自己主动去设置。所以会使用系统的包重新创建随机对象,自然而然的有了如下操作。 r := rand.New(NewSource(time.Now().UnixNano())) 然而这里有坑,虽然标准的随机对象是并发安全的,但是标准包的 NewSource 创建的 Source 并不是并发安全的,如果你仔细阅读,就会发现注释以一个不起眼的方式告知着。 // NewSource returns a new pseudo-random Source seeded with the given value. // Unlike the default Source used by top-level functions, this source is not // safe for concurrent use by multiple goroutines....

November 11, 2020 · 2 min · Kehan Pan