golang

分类下相关文章

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 的官方库, ...

阅读全文...

调用百度翻译接口自动为文章标题生成网址 slug

TODO [X] 中文: 调用翻译接口 [X] 英文: 无需处理,参考 php 里的处理,拼接,去掉指定词 [X] 权限控制:仅限 admin 后台调用 [X] 翻译 api [X] slug api: 还是自己手写吧,减少不必要的依赖。https://github.com/gosimple/slug/blob/master/slug.go [X] 单元测试 [X] publish article page add button [X] 整理 antd form input 添加按钮的流程 百度翻译接口 https://fanyi-api.baidu.com/doc/8 免费版: QP ...

阅读全文...

升级 gopls 到最新版本

写了一段单元测试的代码,在 vim 中提示错误 func TestGenSlug(t *testing.T) { assert.Equal(t, "hello-world", genSlug("Hello World")) } 错误信息为: [gopls] cannot use t (variable of type *testing.T) as assert.TestingT value in argument to assert.Equal: wrong type for method Errorf (have func(format stri ...

阅读全文...

golang 解析 byte slice 类型的 MQTT 消息 payload

MQTT Message payload 的类型 可以看到 payload 函数返回 byte slice 类型。 var f mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { fmt.Printf("TOPIC: %s\n", msg.Topic()) fmt.Printf("MSG: %s\n", msg.Payload()) } type Message interface { Duplicate() bool Qos() byte Retained() ...

阅读全文...

订阅 MQTT 主题后,防止 go 程序退出 main

for 循环会彪 CPU,不好。找了一个 channel 的实现有效解决了这一问题。 实现代码 import ( "os" "os/signal" "syscall" ) func main() { channel := make(chan os.Signal, 1) signal.Notify(channel, os.Interrupt, syscall.SIGTERM) // MQTT 订阅逻辑 // ... <-channel } 代码分析 channel 的发送和接收数据都是阻塞 ...

阅读全文...

MQTT go 客户端发布消息

为了方便客户端测试,搭建好 EMQX 服务之后,需要用 golang 写一个发布消息的测试程序。 用于向指定主题推送消息,这样客户端可以提前测试 MQTT 相关的功能。 安装 Eclipse Paho MQTT Go Client > go get github.com/eclipse/paho.mqtt.golang go: downloading github.com/eclipse/paho.mqtt.golang v1.4.1 go: downloading github.com/gorilla/websocket v1.4.2 go: added github.com/ecl ...

阅读全文...

gin 服务线上没有 systemd 日志的问题

原配置 StandardOutput=append:/some_path/log/access.log StandardError=append:/some_path/log/err.log 我确认了目录权限没有问题。 真正的原因 systemd 版本问题 参考 https://unix.stackexchange.com/questions/321709/redirect-systemd-service-logs-to-file systemd v236 之后支持 file v240 之后支持 append。即每次重启后不会覆盖原文件 而腾讯云上的 systemd 是旧版本的 $ su ...

阅读全文...

gofmt, golint, gopls, govet 的区别

ALEInfo 显示,目前用 NeoVim 打开 go 代码文件时,默认启用了 4 个 linter: Enabled Linters: ['gofmt', 'golint', 'gopls', 'govet'] 其引起的不便是,同一行代码错误,可能会显示两条错误信息。例如, composite literal uses unkeyed fields 这一个问题,显示了两行提示:一个 warning,一个 error。推测是启用了两个 go lint 语法检测。 禁用之前,需要先了解各个工具的功能,及区别。 go vet vet 兽医的意思。。。大概是治疗 go 吉祥物这个大老鼠的吧。 ...

阅读全文...

go warnning: composite literal uses unkeyed fields

在启用了 NeoVim ALE 语法检测插件之后,我发现自己的代码到处都是各种警告,无论是 JS 还是 Go。 而 Go 代码中经常出现的警告信息就是 composite literal uses unkeyed fields。 例如,在使用 Gin I18N 实现多语言翻译的功能时: 警告信息 i18n/i18n.go|32 col 23-45 warning| github.com/gin-contrib/i18n.EmbedLoader composite literal uses unkeyed fields composite: 合成的 出问题的代码: Loader: & ...

阅读全文...

go build tag 实现开发环境与生产环境采用不同的 embed.FS 策略

通过 go embed.FS 将 gin 模板及静态资源文件打包进二进制程序 确实非常方便在服务器上部署、更新程序,但是开发环境调试前端代码就非常麻烦了。 因为每次修改都需要重新编译。 所以,我想利用 go build tag 条件编译来实现,开发环境不启用 embed.FS,只在发布时使用。 重命名问题 xxx redeclared in this block build tag 的互斥来解决。即 //go:build !prod //go:build prod 省略任何一个,如果定义了同名的函数,或者变量,都会导致重复声明的问题。 文件命名来区分 绞尽脑汁起名 load.go / l ...

阅读全文...