高性能go开发建议
(1)尽可能的使用:=去初始化声明一个变量(在函数内部)
(2)尽可能的使用字符代替字符串
(3)尽可能的使用切片代替数组
(4)尽可能的使用数组和切片代替映射
(5)如果只想获取切片中某项值,不需要值的索引,尽可能的使用for range去遍历切片,这比必须查询切片中的每个元素要快一些
(6)当数组元素是稀疏的(例如有很多0值或者空值nil),使用映射会降低内存消耗
(7)初始化映射时指定其容量
(8)当定义一个方法时,使用指针类型作为方法的接受者
(9)在代码中使用常量或者标志提取常量的值
(10)尽可能在需要分配大量内存时使用缓存
(11)使用缓存模板
组件
字符串 strings
strings
strings.Split(s, sep) 用于自定义分割符号来对指定字符串进行分割,同样返回 slice。
strings.Join(sl []string, sep string) string //Join() 用于将元素类型为 string 的 slice 使用分割符号来拼接组成一个字符串
strings.Contains(s, "f")
strings.HasPrefix(s, prefix string) bool
strings.HasSuffix(s, suffix string) bool
strings.Index(s, str string) int
strings.LastIndex(s, str string) int
strings.Replace(str, old, new string, n int) string
strings.Count(s, str string) int
strings.Repeat(s, count int) string
strings.TrimSpace(s) 来剔除字符串开头和结尾的空白符号;
如果你想要剔除指定字符,则可以使用 strings.Trim(s, "cut") 来将开头和结尾的 cut 去除掉。该函数的第二个参数可以包含任何字符,
如果你只想剔除开头或者结尾的字符串,则可以使用 TrimLeft() 或者 TrimRight() 来实现。
strings.ToUpper(item)
strings.NewReader(str) 用于生成一个 Reader 并读取字符串中的内容,然后返回指向该 Reader 的指针,从其它类型读取内容的函数还有:
Read() 从 []byte 中读取内容。
ReadByte() 和 ReadRune() 从字符串中读取下一个 byte 或者 rune
数据结构
gods
切片slice
map
map 默认无序
如果你想为 map 排序,需要将 key(或者 value)拷贝到一个切片,再对切片排序(使用 sort 包,详见第 7.6.6 节),然后可以使用切片的 for-range 方法打印出所有的 key 和 value。
import (
"fmt"
"sort"
)
var (
barVal = map[string]int{"alpha": 34, "bravo": 56, "charlie": 23,
"delta": 87, "echo": 56, "foxtrot": 12,
"golf": 34, "hotel": 16, "indio": 87,
"juliet": 65, "kili": 43, "lima": 98}
)
func main() {
fmt.Println("unsorted:")
for k, v := range barVal {
fmt.Printf("Key: %v, Value: %v / ", k, v)
}
keys := make([]string, len(barVal))
i := 0
for k, _ := range barVal {
keys[i] = k
i++
}
sort.Strings(keys)
fmt.Println()
fmt.Println("sorted:")
for _, k := range keys {
fmt.Printf("Key: %v, Value: %v / ", k, barVal[k])
}
}
堆包
container/heap
双向链表
container/list
类型转换
strconv
strconv包提供了字符串和数字之间的转换功能,可以方便地进行类型转换。
strconv.Itoa(int(bytesLength / 1024)) //将int转换为字符串
strconv.Atoi(s string) (i int, err error) //将字符串转换为int
cast: 不需要panic!在Go语言中进行类型转换易如反掌且安全。
collection: “Collection”为处理数据数组提供了一个流畅、方便的封装。你可以使用“Collect()”方法将一个map或者数组轻松地转换成一个Collection。然后,你可以使用Collection提供的强大而优雅的API来处理数据。
Json
json包
提供了JSON格式的编解码功能,可以方便地处理JSON数据。
type User struct{
Name string `json:"name"`
Age int `json:"age"`
}
user := {"zhangsan", 20}
// 实体转json
jsonStr, err = json.Marshal(user);
fmt.Printf("%s\n", jsonStr);
myUser := User{}
// json转实体
myUser, err = json.Unmarshal(&jsonStr);
fmt.Printf("%v\n", myUser);
gjson: 非常好用的json解析工具库
json-to-go 给你一个json结构的数据,能够将代码转换为对应的结构体,直接在代码中使用,这简直太方便~
命令行参数 flag
flag包提供了解析命令行参数的功能,可以方便地获取用户输入的参数。
cobra: 是一个功能强大的命令行工具库,我们用它来实现内部的命令行工具
反射 reflect
reflect包提供了反射的功能,可以在程序运行时动态地获取和修改对象的信息。
日期时间 time
time
time包提供了时间相关的函数,包括获取当前时间、时间格式化、时间操作等功能。
time.Now()
time.Sleep(1 * time.Second)
now 时间工具库
数字 Math
Decimal
decimal 精度计算
异常 error
errors:更强大的异常堆栈
error 包装用法
func httpRequestHandler(w http.ResponseWriter, req *http.Request) {
err := func () error {
if req.Method != "GET" {
return errors.New("expected GET")
}
if input := parseInput(req); input != "command" {
return errors.New("malformed command")
}
// 可以在此进行其他的错误检测
} ()
if err != nil {
w.WriteHeader(400)
io.WriteString(w, err)
return
}
doSomething() ...
}
翻译
go-pinyin: 汉字转拼音
对象复制
copier: 一个数据复制的库,与 Java 中的 BeanUtils.copy() 类似;可以将两个字段相同但对象不同的 struct 进行数据复制,也支持深拷贝。
验证
govalidator: 使用简单规则验证Go语言的请求数据。受Laravel请求验证启发。
govalidator: 一个用于字符串、结构体和集合的验证器和过滤器包,基于validator.js。
ozzo-validation: 提供可配置和可扩展的数据验证功能
validate: Go通用的数据验证与过滤库,使用简单,内置大部分常用验证器、过滤器,支持自定义验证器、自定义错误消息、字段翻译。
验证码
aj-captcha-go: AJ-Captcha行为验证码的Go实现包
base64Captcha: 图像验证码
wechat: WeChat SDK for Go (微信SDK:简单、易用)
wechat-go: go version wechat web api and message framework for building wechat robot
微信开发
支付
gopay: 微信、支付宝、通联支付、拉卡拉、PayPal、Apple 的Go版本SDK。【极简、易用的聚合支付SDK】
dongfeng-pay: 聚合支付,支付系统 前后端齐全
Excel
excelize: 读取和写入XLAM / XLSM / XLSX / XLTM / XLTX文件。它支持读取和写入Microsoft Excel™ 2007及以上版本生成的电子表格文档。该库通过高度兼容性支持复杂的组件,并提供流式API,以从具有大量数据的工作表中生成或读取数据。此库需要 Go 版本1.16或更高版本。您可以使用go的内置文档工具查看完整文档,或在线查看 go.dev 和文档参考。
Word
unioffice: 文档 (docx) [Word] 读/写/编辑 格式化 图片 表格 Word 转 PDF (docx to pdf) 电子表格 (xlsx) [Excel] 读/写/编辑
图像
imaging: Package imaging 提供了基本的图像处理功能(如调整大小、旋转、裁剪、亮度/对比度调整等)。
gg: gg是一个使用纯Go语言渲染2D图形的库。
gopdf: gopdf是一个用Go语言编写的生成PDF文档的简单库。
gofpdf: gofpdf是一个实现了基于高级支持文本、绘图和图像的PDF文档生成器。
文件 IO
oss: 超轻量级Golang文件服务器
io包
提供了读写数据的基本工具,大部分标准库中输入输出相关的包均依赖于此包。
filename := filePath + ".txt"
body, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
bufio包
在 io 包的基础上提供更高级的读写缓冲
runtime
提供了与运行时系统进行交互的接口
OS
os包提供了与操作系统交互的函数,包括文件操作、进程管理、环境变量等功能
工具库
lancet: 实用go工具库
knife: go工具库
gox: Golang 工具集
gobox: Golang工具集
gotool: 轻量级的Golang工具库(无第三方库依赖)
go工具库: go开发中常用的工具
utils: 基于Go Mod的Golang常用开发工具包utils,包括字符串处理、日期转换、类型转换、切片处理、压缩、加密等
Go通用工具: Go的通用基础工具。
gokit: 一套小而全的 Go 工具包。
config: Go config manage(load,get,set). support JSON, YAML, TOML, INI, HCL. multi file load, data override merge. go应用配置加载管理,支持多种格式,多文件加载,支持数据合并.
代码生成工具
gen: GORM Gen 代码生成
generate: go代码生成工具,支持postgresql、msql逆向生成CRUD代码
GoApi-Generator: 基于GORM&Gin的api自动生成器
gorm-reverse: gorm反向生成实体类和json类
Devops 工具
Yearning: A most popular sql audit platform for mysql
gitea: Git with a cup of tea! Painless self-hosted all-in-one software development service, including Git hosting, code review, team collaboration, package registry and CI/CD
env: 这个库可以将我们的 环境变量 转换为一个 struct
dig: 一个依赖注入库
所有的对象都是单例。有一个统一的地方管理对象。使用时直接传递对象当做参数进来即可(容器会自动注入)。
sql2gorm: 用于将 sql 语句转换为 golang 的 struct
gowatch: 热编译工具
优雅的重启Http服务
revive: golang 代码质量检测工具
starcharts: Plot your repository stars over time.
lux: Fast and simple video download library and CLI tool written in Go
sponge_examples: Some examples of using sponge to develop go projects.
百灵快传:基于Go语言的高性能 “手机电脑超大文件传输神器”、“局域网共享文件服务器”
Fyne: 是一个 Go 语言开发的易用的 UI工具包,提供基于 OpenGL 的跨平台图形界面应用开发支持
gofs: 基于Golang开发的一款开箱即用的跨平台实时文件同步工具
调试工具
perf: 代理工具,支持内存,cpu,堆栈查看,并支持火焰图
go-torch: 快捷定位程序问题
gops: A tool to list and diagnose Go processes currently running on your system
vagrant 开发环境管理工具,单机搭建可移植工具的利器。支持多种虚拟机后端。类似于docker
nomad 轻量级容器调度工具 可以非常方便的管理容器和传统应用,相比 k8s 来说,简单不要太多.
vault 敏感信息和密钥管理工具
weaver 高度可配置化的 http 转发工具,基于 etcd 配置。
supervisor 进程监控工具
foreman 基于procFile进程管理工具. 相比 supervisor 更加简单。
whistle 基于 http,https,websocket 的调试代理工具,配置功能丰富。在线教育的 nohost web 调试工具,基于此开发.
CloudXNS-DDNS 动态域名
fileboy: fileboy,文件变更监听通知工具,使用 Go 编写。适用于 Hot Reload (典型的如开发go项目,无需每次手动执行 go build;又比如前端 node 打包) 或者 系统监控的场景。
示例代码
gin+gorm示例项目
Web 框架
gin
gin中文文档
gin: gin是一款轻量级的Web框架,具有高性能和易用性的特点,可以快速开发Web应用。
gin-vue-admin: 基于vite+vue3+gin搭建的开发基础平台(支持TS,JS混用),集成jwt鉴权,权限管理,动态路由,显隐可控组件,分页封装,多点登录拦截,资源权限,上传下载,代码生成器,表单生成器,chatGPT自动查表等开发必备功能。
go-gin-api: 基于 Gin 进行模块化设计的 API 框架,封装了常用功能,使用简单,致力于进行快速的业务研发。比如,支持 cors 跨域、jwt 签名验证、zap 日志收集、panic 异常捕获、trace 链路追踪、prometheus 监控指标、swagger 文档生成、viper 配置文件解析、gorm 数据库组件、gormgen 代码生成工具、graphql 查询语言、errno 统一定义错误码、gRPC 的使用、cron 定时任务 等等。
ferry: 基于Gin + Vue + Element UI前后端分离的工单系统
go-admin: go-admin是基于golang快速搭建可视化数据管理后台的框架
go-admin: 基于Gin + Vue + Element UI的前后端分离权限管理系统脚手架(初始化简单,只需要配置文件中修改数据库连接,启动后会自动初始化数据库信息以及必须的基础数据)
gin-admin: 基于 Golang + GIN + GORM+ CASBIN + WIRE + Ant Design React的RBAC权限管理脚手架
gin-x: Gin-x 提供更多的组件,让 Gin 框架开发更加高效。
gf
gf: GoFrame is a modular, powerful, high-performance and enterprise-class application development framework of Golang.
beego
beego: beego是一款全功能的Web框架,具有MVC架构、ORM、路由、缓存、Session等功能。
iris
iris: The fastest HTTP/2 Go Web Framework. New, modern and easy to learn. Fast development with Code you control. Unbeatable cost-performance ratio 🚀
echo
echo: echo是一款高性能的Web框架,具有路由、中间件、模板等功能,适合构建RESTful API。
revel: A high productivity, full-stack web framework for the Go language.
微服务框架
go-zero: go-zero是一个集成了各种工程实践的web和rpc框架。
Go kit - A toolkit for microservices
Istio
jupiter: Governance-oriented Microservice Framework.
dapr: Dapr is a portable, event-driven, runtime for building distributed applications across cloud and edge.
DI依赖注入
yoyogo: YoyoGo is a simple, light and fast , dependency injection based micro-service framework written in Go. Support Nacos ,Consoul ,Etcd ,Eureka ,kubernetes.
开发框架
PandaX: 企业级低代码快速开发框架
gin-vue-admin: 基于vite+vue3+gin+gorm前后端分离搭建的开发基础平台,集成jwt鉴权,权限管理,动态路由,分页封装,多点登录拦截,资源权限,上传下载,代码生成器,表单生成器等开发必备功能,五分钟一套CURD前后端代码
ginfast: 基于gin、gorm的后台;可使用ruoyi前端;支持go代码生成
KVA-VUE-ADMIN: 一个基于vue和gin开发的全栈前后端分离的开发基础平台,拥有jwt鉴权,动态路由,动态菜单,代码生成器等功能
Go-Gin-Api: 基于 Gin 进行模块化设计的 API 框架,封装了常用功能,操作简单,致力于进行快速的业务研发。比如,jwt 签名验证、zap 日志收集、panic 异常捕获、swagger 文档生成、viper 配置文件解析、gorm 数据库组件、v2.0支持后台管理,使用Light Year Admin 模板、支持命令工具生成Model、初始化数据库 等等
容器编排
eip-work/kuboard-press: Kuboard 是基于 Kubernetes 的微服务管理界面
Rainbond: 不用懂 Kubernetes 的云原生应用管理平台
k8s kubernetes: Production-Grade Container Scheduling and Management
异步并发 锁
tunny
goworker
async
go-goes: 50行代码实现非常简洁的Goroutines协程池
pool: 简单的golang协程工作池
原子操作 sync/atomic
// 原子操作版加函数
func atomicAdd() {
atomic.AddInt64(&sumCount, 1)
wg.Done()
}
并发控制工具 sync.WaitGroup
本质上是一个并发计数器,暴露出来的核心方法有三个:
WaitGroup.Add(n):完成一次登记操作,使得 WaitGroup 中并发计数器的数值加上 n. 在使用场景中,WaitGroup.Add(n) 背后的含义是,注册并启动了 n 个子 goroutine
WaitGroup.Done():完成一次上报操作,使得 WaitGroup 中并发计数器的数值减 1. 在使用场景中,通常会在一个子 goroutine 退出前,会执行一次 WaitGroup.Done 方法
WaitGroup.Wait():完成聚合操作. 通常由主 goroutine 调用该方法,主 goroutine 会因此陷入阻塞,直到所有子 goroutine 都已经执行完成,使得 WaitGroup 并发计数器数值清零时,主 goroutine 才得以继续往下执行
示例1
批量发出 RPC 或者 HTTP 请求:
requests := []*Request{...}
wg := &sync.WaitGroup{}
wg.Add(len(requests))
for _, request := range requests {
go func(r *Request) {
defer wg.Done()
// res, err := service.call(r)
}(request)
}
wg.Wait()
示例2
var wg sync.WaitGroup
func runTask(id int) {
// 推出一个减去1
defer wg.Done()
fmt.Printf("task %d start..\n", id)
time.Sleep(2 * time.Second)
fmt.Printf("task %d complete\n", id)
}
func asyncRun() {
for i := 0; i < 10; i++ {
go runTask(i + 1)
// 没启动一个go routine 就+1
wg.Add(1)
}
}
func main() {
asyncRun()
wg.Wait()
}
并发实现数据聚合示例
版本一:
func Test_waitGroup(t *testing.T) {
tasksNum := 10
dataCh := make(chan interface{})
resp := make([]interface{}, 0, tasksNum)
stopCh := make(chan struct{}, 1)
// 启动读 goroutine
go func() {
for data := range dataCh {
resp = append(resp, data)
}
stopCh <- struct{}{}
}()
// 保证获取到所有数据后,通过 channel 传递到读协程手中
var wg sync.WaitGroup
for i := 0; i < tasksNum; i++ {
wg.Add(1)
go func(ch chan<- interface{}) {
defer wg.Done()
ch <- time.Now().UnixNano()
}(dataCh)
}
// 确保所有取数据的协程都完成了工作,才关闭 ch
wg.Wait()
close(dataCh)
// 确保读协程处理完成
<-stopCh
t.Logf("resp: %+v", resp)
}
版本二:
func Test_waitGroup(t *testing.T) {
tasksNum := 10
dataCh := make(chan interface{})
// 启动写 goroutine,推进并发获取数据进程,将获取到的数据聚合到 channel 中
go func() {
// 保证获取到所有数据后,通过 channel 传递到读协程手中
var wg sync.WaitGroup
for i := 0; i < tasksNum; i++ {
wg.Add(1)
go func(ch chan<- interface{}) {
defer wg.Done()
ch <- time.Now().UnixNano()
}(dataCh)
}
// 确保所有取数据的协程都完成了工作,才关闭 ch
wg.Wait()
close(dataCh)
}()
resp := make([]interface{}, 0, tasksNum)
// 主协程作为读协程,持续读取数据,直到所有写协程完成任务,chan 被关闭后才会往下
for data := range dataCh {
resp = append(resp, data)
}
t.Logf("resp: %+v", resp)
}
``
互斥锁 sync.Mutex
定义了一个计数器count,并创建了一个互斥锁lock。然后启动了100个goroutine,并在每个goroutine中对计数器进行加1操作。由于对count的访问是并发的,所以我们需要使用互斥锁来防止竞态条件的发生。
```go
package main
import (
"fmt"
"sync"
)
var (
count int
lock sync.Mutex
)
func main() {
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
lock.Lock()
count++
lock.Unlock()
wg.Done()
}()
}
wg.Wait()
fmt.Println(count)
}
读写锁 sync.RWMutex
首先启动100个goroutine对计数器进行加1操作,在这段时间内,计数器只能被一个线程独占。然后再启动100个goroutine读取计数器的值,这些goroutine可以同时读取计数器的值。
与互斥锁相比,读写锁具有更高的并发性和更少的锁竞争。如果大部分操作都是读操作,那么使用读写锁代替互斥锁可以提高性能
package main
import (
"fmt"
"sync"
)
var (
count int
rw sync.RWMutex
)
func main() {
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
rw.Lock()
count++
rw.Unlock()
wg.Done()
}()
}
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
rw.RLock()
fmt.Println(count)
rw.RUnlock()
wg.Done()
}()
}
wg.Wait()
}
只执行一次 sync.Once
func main() {
o := &sync.Once{}
for i := 0; i < 10; i++ {
o.Do(func() {
fmt.Println("only once")
})
}
}
$ go run main.go
only once
条件变量 sync.Cond
它可以让一组的 Goroutine 都在满足特定条件时被唤醒。每一个 sync.Cond 结构体在初始化时都需要传入一个互斥锁
示例定义了一个计数器count和一个等待线程的计数waiters。然后启动10个goroutine来等待计数器达到5,并在计数器达到5时输出计数器的值。再启动5个goroutine来对计数器进行加1操作。当计数器达到5时,调用cond.Signal()来唤醒等待的goroutine。
需要注意的是,在使用条件变量之前必须获取互斥锁,否则将出现死锁
package main
import (
"fmt"
"sync"
)
var (
count int
waiters int
lock sync.Mutex
cond *sync.Cond = sync.NewCond(&lock)
)
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
lock.Lock()
for count < 5 {
waiters++
cond.Wait()
waiters--
}
fmt.Println("Count:", count)
lock.Unlock()
wg.Done()
}()
}
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
lock.Lock()
count++
if waiters > 0 {
cond.Signal()
}
lock.Unlock()
wg.Done()
}()
}
wg.Wait()
}
示例2
var status int64
func main() {
c := sync.NewCond(&sync.Mutex{})
for i := 0; i < 10; i++ {
go listen(c)
}
time.Sleep(1 * time.Second)
go broadcast(c)
ch := make(chan os.Signal, 1)
signal.Notify(ch, os.Interrupt)
<-ch
}
func broadcast(c *sync.Cond) {
c.L.Lock()
atomic.StoreInt64(&status, 1)
c.Broadcast()
c.L.Unlock()
}
func listen(c *sync.Cond) {
c.L.Lock()
for atomic.LoadInt64(&status) != 1 {
c.Wait()
}
fmt.Println("listen")
c.L.Unlock()
}
$ go run main.go
listen
...
listen
自定义超时互斥锁、读写锁工具
syncUtil.go
/*
由于Go不提供超时锁,所以自己实现了支持超时机制的互斥锁Locker和读写锁RWLocker。
为了方便供第三方程序使用,提供了根据Key获取超时互斥锁和超时读写锁的复合对象LockerUtil和RWLockerUtil。
为了在出现锁超时时方便查找问题,会记录上次成功获得锁时的堆栈信息;并且在本次获取锁失败时,同时返回上次成功时的堆栈信息和本次的堆栈信息。
*/
package syncUtil
const (
// 默认超时的毫秒数(1小时)
con_Default_Timeout_Milliseconds = 60 * 60 * 1000
// 写锁每次休眠的时间比读锁的更短,这样是因为写锁有更高的优先级,所以尝试的频率更大
// 写锁每次休眠的毫秒数
con_Lock_Sleep_Millisecond = 1
// 读锁每次休眠的毫秒数
con_RLock_Sleep_Millisecond = 2
)
// 获取超时时间
func getTimeout(timeout int) int {
if timeout > 0 {
return timeout
} else {
return con_Default_Timeout_Milliseconds
}
}
locker.go
package syncUtil
import (
"fmt"
"runtime/debug"
"sync"
"time"
)
// 写锁对象
type Locker struct {
write int // 使用int而不是bool值的原因,是为了与RWLocker中的read保持类型的一致;
prevStack []byte
mutex sync.Mutex
}
// 内部锁
// 返回值:
// 加锁是否成功
func (this *Locker) lock() bool {
this.mutex.Lock()
defer this.mutex.Unlock()
// 如果已经被锁定,则返回失败
if this.write == 1 {
return false
}
// 否则,将写锁数量设置为1,并返回成功
this.write = 1
// 记录Stack信息
this.prevStack = debug.Stack()
return true
}
// 尝试加锁,如果在指定的时间内失败,则会返回失败;否则返回成功
// timeout:指定的毫秒数,timeout<=0则将会死等
// 返回值:
// 成功或失败
// 如果失败,返回上一次成功加锁时的堆栈信息
// 如果失败,返回当前的堆栈信息
func (this *Locker) Lock(timeout int) (successful bool, prevStack string, currStack string) {
timeout = getTimeout(timeout)
// 遍历指定的次数(即指定的超时时间)
for i := 0; i < timeout; i = i + con_Lock_Sleep_Millisecond {
// 如果锁定成功,则返回成功
if this.lock() {
successful = true
break
}
// 如果锁定失败,则休眠con_Lock_Sleep_Millisecond ms,然后再重试
time.Sleep(con_Lock_Sleep_Millisecond * time.Millisecond)
}
// 如果时间结束仍然是失败,则返回上次成功的堆栈信息,以及当前的堆栈信息
if successful == false {
prevStack = string(this.prevStack)
currStack = string(debug.Stack())
}
return
}
// 锁定(死等方式)
func (this *Locker) WaitLock() {
successful, prevStack, currStack := this.Lock(0)
if successful == false {
fmt.Printf("Locker.WaitLock():{PrevStack:%s, currStack:%s}\n", prevStack, currStack)
}
}
// 解锁
func (this *Locker) Unlock() {
this.mutex.Lock()
defer this.mutex.Unlock()
this.write = 0
}
// 创建新的锁对象
func NewLocker() *Locker {
return &Locker{}
}
rwLocker.go
package syncUtil
import (
"fmt"
"runtime/debug"
"sync"
"time"
)
// 读写锁对象
type RWLocker struct {
read int
write int // 使用int而不是bool值的原因,是为了与read保持类型的一致;
prevStack []byte
mutex sync.Mutex
}
// 尝试加写锁
// 返回值:加写锁是否成功
func (this *RWLocker) lock() bool {
this.mutex.Lock()
defer this.mutex.Unlock()
// 如果已经被锁定,则返回失败
if this.write == 1 || this.read > 0 {
return false
}
// 否则,将写锁数量设置为1,并返回成功
this.write = 1
// 记录Stack信息
this.prevStack = debug.Stack()
return true
}
// 写锁定
// timeout:超时毫秒数,timeout<=0则将会死等
// 返回值:
// 成功或失败
// 如果失败,返回上一次成功加锁时的堆栈信息
// 如果失败,返回当前的堆栈信息
func (this *RWLocker) Lock(timeout int) (successful bool, prevStack string, currStack string) {
timeout = getTimeout(timeout)
// 遍历指定的次数(即指定的超时时间)
for i := 0; i < timeout; i = i + con_Lock_Sleep_Millisecond {
// 如果锁定成功,则返回成功
if this.lock() {
successful = true
break
}
// 如果锁定失败,则休眠con_Lock_Sleep_Millisecond ms,然后再重试
time.Sleep(con_Lock_Sleep_Millisecond * time.Millisecond)
}
// 如果时间结束仍然是失败,则返回上次成功的堆栈信息,以及当前的堆栈信息
if successful == false {
prevStack = string(this.prevStack)
currStack = string(debug.Stack())
}
return
}
// 写锁定(死等)
func (this *RWLocker) WaitLock() {
successful, prevStack, currStack := this.Lock(0)
if successful == false {
fmt.Printf("RWLocker:WaitLock():{PrevStack:%s, currStack:%s}\n", prevStack, currStack)
}
}
// 释放写锁
func (this *RWLocker) Unlock() {
this.mutex.Lock()
defer this.mutex.Unlock()
this.write = 0
}
// 尝试加读锁
// 返回值:加读锁是否成功
func (this *RWLocker) rlock() bool {
this.mutex.Lock()
defer this.mutex.Unlock()
// 如果已经被锁定,则返回失败
if this.write == 1 {
return false
}
// 否则,将读锁数量加1,并返回成功
this.read += 1
// 记录Stack信息
this.prevStack = debug.Stack()
return true
}
// 读锁定
// timeout:超时毫秒数,timeout<=0则将会死等
// 返回值:
// 成功或失败
// 如果失败,返回上一次成功加锁时的堆栈信息
// 如果失败,返回当前的堆栈信息
func (this *RWLocker) RLock(timeout int) (successful bool, prevStack string, currStack string) {
timeout = getTimeout(timeout)
// 遍历指定的次数(即指定的超时时间)
// 读锁比写锁优先级更低,所以每次休眠2ms,所以尝试的次数就是时间/2
for i := 0; i < timeout; i = i + con_RLock_Sleep_Millisecond {
// 如果锁定成功,则返回成功
if this.rlock() {
successful = true
break
}
// 如果锁定失败,则休眠2ms,然后再重试
time.Sleep(con_RLock_Sleep_Millisecond * time.Millisecond)
}
// 如果时间结束仍然是失败,则返回上次成功的堆栈信息,以及当前的堆栈信息
if successful == false {
prevStack = string(this.prevStack)
currStack = string(debug.Stack())
}
return
}
// 读锁定(死等)
func (this *RWLocker) WaitRLock() {
successful, prevStack, currStack := this.RLock(0)
if successful == false {
fmt.Printf("RWLocker:WaitRLock():{PrevStack:%s, currStack:%s}\n", prevStack, currStack)
}
}
// 释放读锁
func (this *RWLocker) RUnlock() {
this.mutex.Lock()
defer this.mutex.Unlock()
if this.read > 0 {
this.read -= 1
}
}
// 创建新的读写锁对象
func NewRWLocker() *RWLocker {
return &RWLocker{}
}
使用输入通道和输出通道代替锁:
func Worker(in, out chan *Task) {
for {
t := <-in
process(t)
out <- t
}
}
channel
channel包 Golang中的一种并发通信机制,可以实现协程之间的数据传递和同步。
context
context包 提供了上下文管理的功能,可以方便地控制并发协程的执行。
timer
timer包定时器相关操作
消息队列
队列
nsq: A realtime distributed messaging platform
asynq: 分布式任务队列 保证至少执行一次任务 重试失败的任务 在工作进程崩溃时自动恢复任务 加权优先级队列 严格优先级队列
Machinery异步队列
YTask: YTask is an asynchronous task queue for handling distributed jobs in golang (go异步任务队列)
IM聊天
go-chat: go-chat.使用Go基于WebSocket开发的web聊天应用。单聊,群聊。文字,图片,语音,视频消息,屏幕共享,剪切板图片,基于WebRTC的P2P语音通话,视频聊天。
go-chat-web: 使用React基于WebSocket的聊天程序,普通文本消息,文件,图片,视频消息,语音消息,视频通话,屏幕共享等。
im_service: golang im server
chat: Instant messaging platform. Backend in Go. Clients: Swift iOS, Java Android, JS webapp, scriptable command line; chatbots
WuKongIM: 高性能通用通讯服务,支持即时通讯(聊天软件)(IM)(Chat),消息推送,消息中台,物联网通讯,音视频信令,直播弹幕,客服系统,AI通讯,即时社区等场景。
aixinge: Ai(智能)Xin(信)Ge(鸽)—— 智能消息推送系统
分布式任务调度
cron: a cron library for go
gocron: Easy and fluent Go cron scheduling
cronsun
gocron
go-queue: 分布式定时任务&极简接口的Kafka Pub/Sub消息队列
jiacrontab: jiacrontab 是一款完全自主设计并实现的定时任务&常驻任务管理工具。 提供了方便的界面用于完全控制系统中运行的定时任务和常驻任务。
测试
testing
func Test(t *testing.T) {
}
monkey 单元测试
gomonkey 是一个 mock 打桩工具,当我们写单元测试时,需要对一些非接口函数进行 mock 会比较困难,这时就需要用到它了
gotests: 自动生成测试用例工具
testify: A toolkit with common assertions and mocks that plays nicely with the standard library
mock: GoMock is a mocking framework for the Go programming language.
sharingan: Sharingan(写轮眼)是一个基于golang的流量录制回放工具,适合项目重构、回归测试等。
quick-mock: 通过配置json,快速构建http请求接口,方便前端和后端数据交互
日志
fmt
fmt.Println(v)
func fmt.Fprintln(w io.Writer, a ...invalid type) (n int, err error)
fmt.Fprintln(w, "hello, world")
log包
提供了日志记录的功能,可以方便地记录程序运行时的信息。
logrus
logrus_mail 邮件通知hooks
zap
logger: 这是一个基于GO语言的服务器日志系统
远程调用
RPC
grpc-go: The Go language implementation of gRPC. HTTP/2 based RPC
rpcx: Best microservices framework in Go, like alibaba Dubbo, but with more features, Scale easily. Try it. Test it. If you feel it’s better, use it! 𝐉𝐚𝐯𝐚有𝐝𝐮𝐛𝐛𝐨, 𝐆𝐨𝐥𝐚𝐧𝐠有𝐫𝐩𝐜𝐱! build for cloud!
tinyrpc: Fast, stable, mini RPC framework based on protocol buffer
http client
req: 简单而强大:简单易用,提供丰富的客户端级和请求级设置,所有设置均为直观的链式方法。
resty: GET、POST、PUT、DELETE、HEAD、PATCH、OPTIONS等简单且可链式调用的设置和请求方法
fasthttp
mux: Package gorilla/mux is a powerful HTTP router and URL matcher for building Go web servers with 🦍
sessions: Package gorilla/sessions provides cookie and filesystem sessions and infrastructure for custom session backends.
websocket
websocket: websocket提供了WebSocket协议的支持,可以实现实时通信的功能。
Restful和gprc相互转换
网络通信
goproxy: Proxy是golang实现的高性能http,https,websocket,tcp,socks5代理服务器,支持内网穿透,链式代理,通讯加密,智能HTTP,SOCKS5代理,黑白名单,限速,限流量,限连接数,跨平台,KCP支持,认证API。
go-sniffer: 可扩展的抓包工具,可以开发自定义协议的工具包 抓包截取项目中的数据库请求并解析成相应的语句。
ngrok 反向代理工具,快捷开放内网端口供外部使用。
cfssl: 配置化生成证书 从根证书,到业务侧证书一键生成.
acme.sh: 免费的证书获取工具 基于 acme 协议,从 letsencrypt 生成免费的证书,有效期 1 年,可自动续期。
Mqtt通信
balancer: 负载均衡 A go library that implements load balancing algorithms. Fast, stable mini layer 7 load balancer.
mkcert: mkcert 是生成本地 HTTPS 加密证书的工具,一个命令就可以生成证书,不需要任何配置
net/http
func IndexHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "hello, world. http: %s", r.URL.Path)
}
func main() {
http.HandleFunc("/", IndexHandler)
http.ListenAndServe(":8080", nil)
}
ping
ping: 检测节点连通性,ping包,及其丢包率
useragent
useragent: HTTP User Agent parser for the Go programming language.
数据库 存储
gorm
gorm: 一个功能齐全的 Golang 对象关系映射库
database/sql
sql包提供了数据库操作的接口,可以方便地连接和操作数据库。)
sqlx: 手写sql
mysql
mysql包提供了MySQL数据库的支持,可以方便地进行MySQL数据库的操作。
xorm 对象关系映射库
redis
redis包
提供了Redis数据库的支持,可以方便地进行Redis数据库的操作。
redis/go-redis: Redis Go client
redigo
codis: Proxy based Redis cluster solution supporting pipeline and scaling dynamically
redis-tools: A collection of redis tools, including distributed lock, cas, casEx, cad
kafka
sarama
es
elastic: 这也是一个非常成熟的 elasticsearch 库。
qax-os/ElasticHD: Elasticsearch 可视化DashBoard, 支持Es监控、实时搜索,Index template快捷替换修改,索引列表信息查看, SQL converts to DSL等
mongo
mongo-go-driver
etcd
etcd: Distributed reliable key-value store for the most critical data of a distributed system
分布式存储
tidb: TiDB is an open-source, cloud-native, distributed, MySQL-Compatible database for elastic scale and real-time analytics. Try AI-powered Chat2Query free at : https://tidbcloud.com/free-trial
kv 存储
lotusdb: Fast k/v storage compatible with lsm tree and b+tree, optimization of badger and bbolt.
gin-cloud-storage: 使用Go语言开发的云存储网盘项目
缓存
go-cache 是一个类似于 Java 中的 Guava cache ,线程安全,使用简单;不需要 分布式缓存 的简单场景可以考虑。
鉴权
iam: 企业级的 Go 语言实战项目:认证和授权系统(带配套课程)
权限控制
jwt: 一个完整的JSON Web Token (JWT)实现。该库支持解析和验证,以及生成和签名JWT。
oauth2: goauth2的后继者。通用OAuth 2.0包,提供JWT、Google APIs、Compute Engine和App Engine支持。
限流
ratelimit
http限流
分布式id
go-snowflake: Go 语言实现的 Snowflake 算法,为分布式系统生成唯一ID,单机测试1秒可生成20万ID。
注册中心
Consul
Api网关
api网关
链路跟踪
jaeger
监控
prometheus
断路器
circuitbreaker: Circuit Breakers in Go
配置
configor 是一个配置文件读取库,支持 YAML /JSON/TOML 等格式。
viper: 兼容 json,toml,yaml,hcl 等格式的日志库
重试
retry: ♻️ The most advanced interruptible mechanism to perform actions repetitively until successful.
静态建站
hugo
hugo: The world’s fastest framework for building websites.
服务器
zinx: A lightweight concurrent server framework based on Golang.(基于Golang轻量级TCP并发服务器框架).
leaf: A game server framework in Go (golang)
livego 直播服务器
爬虫
goquery: A little like that j-thing, only in Go.
crawlab: Crawlab 是一个使用 Golang 开发的分布式爬虫管理平台,支持Python、NodeJS、Go、Java、PHP等多种编程语言以及多种爬虫框架
博客 在线文档
pipe: B3log 分布式社区的 Go 博客端节点系统
BookStack: BookStack,基于MinDoc,使用Beego开发的在线文档管理系统,功能类似Gitbook和看云。
mm-wiki: a markdown mini wiki 一个轻量级的企业知识分享与团队协同软件
fountain: 静态博客生成
gomybolg gin+gorm layui 博客系统
paopao-ce: gin+zinc+vue+ts 清新文艺微社区
GoMD: 使用Golang开发的简洁、易用的Markdown博客系统
Book教程
Go 语言切片的实现原理
golang-developer-roadmap
build-web-application-with-golang
7天用Go从零实现Web框架Gee教程
Go语言高级编程
awesome-go: A curated list of awesome Go frameworks, libraries and software
GolangFamily
Uber Go 语言编码规范中文版
go-awesome: Go 语言优秀资源整理,为项目落地加速
learning_tools: Go 学习、Go 进阶、Go 实用工具类、Go DDD 项目落地、Go-kit 、Go-Micro 、Go 推送平台、微服务实践
参考文档
Wechat-ggGitHub/Awesome-GitHub-Repo: 收集整理 GitHub 上高质量、有趣的开源项目。文章来源:https://www.toymoban.com/news/detail-683221.html
go 语言工具包文章来源地址https://www.toymoban.com/news/detail-683221.html
到了这里,关于github gitee go开发 热门开源项目的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!