golang

分类下相关文章

将 Golang 代码自动转换成 c/c++ 的方案选型

需求来源 因为最近一直在写 Android 蓝牙相关的 App,但是我发现 Kotlin 这门语言来操作字节流很不方便。 比如 CRC/BCC 校验,双字节转换 int16 都不方便。 而且之前还有微信小程序的蓝牙处理逻辑用 js 写的,连 js 都比 kotlin 操作字节流方便。但是也很麻烦。 远不如 c/c++ 代码直观。再就是我还有一套蓝牙网关直连服务器 golang 服务端的一套代码。 需要同时维护三套不同语言的代码,实现同一个逻辑,维护成本很高,而且没有意义。kotlin 和 js 这两个语言实在没有深究的兴趣。 于是我想,是否可以把蓝牙数据包的逻辑改用 c/c++ 编写,然后 ...

阅读全文...

golang gin graceful shutdown

在做一个微信支付的流程,担心经常更新程序导致服务中断,影响退款等逻辑,所以想加上 graceful shutdown 功能。 参考 Golang Gin 官方文档: https://gin-gonic.com/docs/examples/graceful-restart-or-stop/ 使用 Go 1.8 之后内置的 http.Server Shutdown() 方法,以实现 graceful shutdowns。 测试 // 测试 graceful shutdown // /api/testSleep?duration=20s func TestSleep(c *gin.Context) ...

阅读全文...

gorm preload 限制 field 字段

例如,我想用 golang gorm 查询订单表中关联的代理商名称,但是用 Gorm Preload 又会将代理商信息中多余的敏感信息取出来, 例如联系人等信息。于是就需要限制 Preload 的返回字段。 Models type Order struct { gorm.Model AgentId int // 代理商 id Agent Agent // 代理商信息 Status int } type Agent struct { gorm.Model Name string // 代理 ...

阅读全文...

Gorm select 表里所有数据包括已经软删除的数据

又写了一天的 bug ... 被 ORM 折腾死。 没关系,又活了一天,已经很厉害了。。。 Bug 的根源 一个设备信息管理系统的表,里面会自动给设备生成设备 ID。 格式: 前6位为生产如期,如:211207,代表 2021年12月7日生产。 后3位为生产编号,如:001,代表当日生产的第一台设备。 编号的生成逻辑: sql like 取最新的一条 满足 211207 的记录,如果有,就判断最后三位 + 1 没有,就生成一条 001 这个逻辑跑了很久都没有出问题,但是今天在写一个新系统时,我偷懒 copy 过来了。 然后,另一个 bug 导致几条设备信息被软删除 (gorm 默认是使 ...

阅读全文...

swaggo 通过 tag 限制生成接口文档的范围

这个周都在写 swaggo 接口文档,起因是要迁移一个旧的 golang gin 后台接口服务,新的系统只需要用到部分原有系统的接口。 但是,为了预防未来可能功能扩展,还是想继续保留原有系统的接口文档,不做删除处理。 那么,在用 swaggo 生成接口文档的时候,就出现了问题。如何屏蔽掉不需要的接口文档? 看起来很简单,直接用 exclude 参数不就行了?实际测试,这个 exclude 参数只支持目录,不支持具体文件,虽然 帮助文档里写是支持具体文件,但是即便更新了最新版本的 swaggo,也是不生效。 后来发现新版本支持了 tags 来指定生成文档。这就满足需求了,而且 tag 控制精度比 ...

阅读全文...

Golang Gin API 接口限速

需求 在做一个基于图片文字识别的题库管理系统,使用 Golang 调用百度 OCR 文字识别接口, 但是百度 OCR 接口有调用频率限制: 免费版的 QPS 为 2。即每秒最多调用两次 付费版的 QPS 为 10 如果不限速,就会报错: {"error_code":18,"error_msg":"Open api qps request limit reached"} 而前端在上传图片时,是支持多个图片批量上传的,且会有多人同时上传。 那么就需要一个限制接口速度的功能。 备选方案 方案一:通过队列来处理,单个 worker 方 ...

阅读全文...

百度 OCR 文字识别 golang SDK

免费额度 目前使用的是个人认证: 通用文字识别(标准版) 1000次/月赠送 通用文字识别(标准含位置版) 1000次/月赠送 通用文字识别(高精度版)1000次/月赠送 通用文字识别(高精度含位置版)500次/月赠送 注意:需要手动去点击认领免费额度。 QPS 免费版的 QPS 为 2 付费版的 QPS 为 10 Go SDK 文字识别,官方没有提供 Golang 版本的 SDK。 找到一个三方的实现: https://github.com/chenqinghe/baidu-ai-go-sdk/tree/master/example/vision/ocr 但是示例代码有些问题,需要查 ...

阅读全文...

gorm soft delete 的唯一索引问题

bug 今天测试我的添加、修改接口时,发现一个联合唯一索引不生效。 有问题的表结构: CREATE TABLE `card` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `deleted_at` datetime DEFAULT NULL, `created_at` datetime DEFAULT NULL, `updated_at` datetime DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `ux_name_del` ...

阅读全文...

gorm many2many 导致 [gopls] import cycle not allowed

今天第一次遇到 go 的循环引用问题: [gopls] import cycle not allowed 起因 新项目使用了新的包结构,每个 model 及对应 controller 放到独立的 package 中。 而不是两个大 models 目录,controllers 目录。 恰好一个 gorm many2many 关系导致两个 package 相互依赖,例如,文章及标签。 article 和 tag 这俩个 model 引起了 import cycle。 go 为何要禁止 import cycle 提升编译速度。 解决办法 Packages are compilation uni ...

阅读全文...

go gin 打印日志到文件

由于低版本的 systemd 不支持 append 记录日志的方式,所以用代码实现了 gin 写入日志到文件的功能。但是会发现日志文件只记录了 gin 路由的信息,而自己通过 log.Printf 打印的日志,并没有记录下来。 通过已记录日志的关键字 GIN debug 前缀,找到了 gin 里日志的实现。 GIN-debug: debugPrint func debugPrint(format string, values ...any) { if IsDebugging() { if !strings.HasSuffix(format, "\n") { fo ...

阅读全文...

golang 给微信小程序码图片底部添加文字

需求 由于要做硬件设备的扫码支付,生产的时候为了方便硬件屏幕上确认部署的支付码跟设备匹配,需要在微信小程序码的底部添加上标识文字, 例如设备 ID 之类的。 效果演示 还是三方库好用 https://github.com/fogleman/gg 比用 golang 自带库方便太多了。否则实现添加个文字,脑子爆炸。 字体下载 https://fonts.google.com/ 图片上添加文字,就涉及到文本字体的选择,可以在 google fonts 上根据语种需要选择字体。 实现逻辑 先生成一张白色底的大背景图,宽度为原小程序码的宽度,高度加上了文字的高度 然后将原小程序图片复制到背景图的顶 ...

阅读全文...

gin.BasicAuth 为生产环境 Swagger UI 文档加上密码保护

虽然大家都推荐将 Swagger 接口文档服务部署在开发环境,但是由于现公司前后端开发人员异地办公,我还是倾向于将 swaggo 服务部署在生产环境。加上个简单的账号密码访问限制即可。 方案选型 Nginx auth golang gin auth 最终,我选择了 gin basic auth 的方案,主要是写在代码里,省去了线上一丢丢地配置麻烦。以后迁移服务器也不用太操心。 安全问题 url 中不使用 swagger 前缀,防止 swagger 出现比较大的漏洞,被人扫出漏洞。例如这里使用了 api-doc,虽然也很容易被猜出。。。还是自己想个复杂的 url 前缀比较安全。 实现代码 ...

阅读全文...

go-swagger 生成 API 文档,及与 swaggo 的对比

go-swagger 与 swaggo 对比 最终没有选择 go-swagger,还是回归了 swaggo。原因: go-swagger 生成文档的速度奇慢无比。我一个 20 多个文件的项目,要整整 30 秒。而 swaggo 可以 5 秒完成。 go-swagger 上手困难。官方文档不友好,没有一个简单清晰的示例说明。 虽然 swaggo 格式规范丑一点,但是至少上手容易,可以直接干活。 这个文章做的对比相对客观一点: https://ldej.nl/post/generating-swagger-docs-from-go/ 再就是我跟上面作者的观点一致,就是这两个货其实都很丑陋,这样 ...

阅读全文...

使用 swaggo 及 gin-swagger 生成 API 文档

好久没有给别人写接口了,正好遇到一个前后端合作的项目,是时候尝试一下 golang swagger 的 API 文档生成工具了。 注意:尝试了 swaggo 之后,感觉很不好(注释规范口味太重,与三方库有冲突),我觉得再试试 go-swagger。但是没想到 go-swagger 更难上手,且生成速度巨慢,无法接受,还是继续使用 swaggo。 使用 swagger 的好处 返回的数据结构,可以直接引用 struct 的定义:https://github.com/swaggo/swag , 但是同时带来了问题,如果 struct 里嵌入了三方库的类型,依赖检测时会出现与 swaggo 规范冲 ...

阅读全文...

golang 实现蓝牙体征监测设备数据上报及存储的频率控制

需求背景 蓝牙体征检测设备的初始上报频率非常高,单台每秒 370 个数据包。 需要通过通过服务器向蓝牙网关下发禁止波形数据的指令,禁用掉无用数据的上报。 有两个禁用策略: 定时下发禁用指令。例如每十秒 收到波形数据时,就立即下发禁用指令 显然第二种方式更合理,而且在有多台设备接入的情况下,也方便批量下发(根据 mac 地址)。 但是,这里就出现了一个频率控制问题,就是从下发指令,到禁止成功,是有一个时间间隔的。这个时间间隔内,要规避重复下发指令。 同时,还有另外一个需求,就是对写入数据进行控制,设备方的体温上报频率过高,增加了存储成本,所以同样需要限制。 找到一个 golang 的官方库, ...

阅读全文...