Go工具之generate

2,965 阅读4分钟

本文给大家介绍Go的一个实用技巧,该技巧主要通过go工具实现。

传统写法

大家经常碰到命名错误码、状态码的同时,又要同步写码对应的翻译,有没有感觉很无聊。这里举一个例子:

package main

import "fmt"

// 定义错误码
const (
   ERR_CODE_OK             = 0 // OK
   ERR_CODE_INVALID_PARAMS = 1 // 无效参数
   ERR_CODE_TIMEOUT        = 2 // 超时
)

// 定义错误码与描述信息的映射
var mapErrDesc = map[int]string{
   ERR_CODE_OK:             "OK",
   ERR_CODE_INVALID_PARAMS: "无效参数",
   ERR_CODE_TIMEOUT:        "超时",
}

// 根据错误码返回描述信息
func GetDescription(errCode int) string {
   if desc, exist := mapErrDesc[errCode]; exist {
      return desc
   }

   return fmt.Sprintf("error code: %d", errCode)
}

func main() {
   fmt.Println(GetDescription(ERR_CODE_OK))
}

这是一种重复性操作,没有什么技术含量,另外很可能忘记写映射。我只想写错误码,对应的描述信息直接用注释里的就行,所以这里介绍一下对应的工具。

go generate

go有很多工具,大家可以通过go命令查看。

![image-20210321123427848](/Users/bytedance/Library/Application Support/typora-user-images/image-20210321123427848.png)

go generate是 Go 自带的工具。使用命令go generate执行。go generate是利用源代码中的注释工作的。格式如下:

//go:generate command arg1 arg2

这样在同一个目录下执行命令go generate就会自动运行命令command arg1 arg2command可以是在PATH中的任何命令,应用非常广泛。配合stringer命令可以为给定类型生成String方法,就可以实现我们的想法。

安装stringer

stringer不是Go自带工具,需要手动安装。执行如下命令即可

go get golang.org/x/tools/cmd/stringer

注意点

  1. 需要配置gomod
  2. 需要设置好目录,当前目录结构如下

image-20210321144721406.png

使用

有两种执行方案,

一种是在errcode中,增加注释//go:generate stringer -type ErrCode -linecomment

另一种是直接命令行执行stringer -type ErrCode -linecomment

执行完毕会发现自动生成新文件

image-20210321144937463.png

关于stringer的命令,大家可以通过stringer -h查看

源码

下面是整个源码:

main.go

package main

import (
   "fmt"
   "myproject/enum"
)

func main() {
   fmt.Println(enum.ERR_CODE_OK)
}

errcode.go

package enum

type ErrCode int64 //错误码
const (
   ERR_CODE_OK             ErrCode = 0 // OK
   ERR_CODE_INVALID_PARAMS ErrCode = 1 // 无效参数
   ERR_CODE_TIMEOUT        ErrCode = 2 // 超时
)

stringer生成的文件

// Code generated by "stringer -type ErrCode -linecomment"; DO NOT EDIT.

package enum

import "strconv"

func _() {
   // An "invalid array index" compiler error signifies that the constant values have changed.
   // Re-run the stringer command to generate them again.
   var x [1]struct{}
   _ = x[ERR_CODE_OK-0]
   _ = x[ERR_CODE_INVALID_PARAMS-1]
   _ = x[ERR_CODE_TIMEOUT-2]
}

const _ErrCode_name = "OK无效参数超时"

var _ErrCode_index = [...]uint8{0, 2, 14, 20}

func (i ErrCode) String() string {
   if i < 0 || i >= ErrCode(len(_ErrCode_index)-1) {
      return "ErrCode(" + strconv.FormatInt(int64(i), 10) + ")"
   }
   return _ErrCode_name[_ErrCode_index[i]:_ErrCode_index[i+1]]
}

执行结果显示如下:

➜ myproject go run main.go OK

总结

使用stringer可以帮我们节省很多时间,除了stringer外,还有gostringer,大家感兴趣可以试一下。

资源

  1. pkg.go.dev/golang.org/…
  2. studygolang.com/articles/22…
  3. blog.csdn.net/weixin_3934…
  4. blog.golang.org/generate
  5. docs.google.com/document/d/…
  6. blog.csdn.net/qq_31362439…
  7. pkg.go.dev/github.com/…

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

我的个人博客为:shidawuhen.github.io/

往期文章回顾:

技术

  1. Go工具之generate
  2. Go设计模式(4)-代码编写
  3. Go单例实现方案
  4. Go设计模式(4)-代码编写
  5. Go设计模式(3)-设计原则
  6. Go设计模式(2)-面向对象分析与设计
  7. 支付接入常规问题
  8. HTTP2.0基础教程
  9. Go设计模式(1)-语法
  10. MySQL开发规范
  11. HTTPS配置实战
  12. Go通道实现原理
  13. Go定时器实现原理
  14. HTTPS连接过程
  15. 限流实现2
  16. 秒杀系统
  17. 分布式系统与一致性协议
  18. 微服务之服务框架和注册中心
  19. Beego框架使用
  20. 浅谈微服务
  21. TCP性能优化
  22. 限流实现1
  23. Redis实现分布式锁
  24. Golang源码BUG追查
  25. 事务原子性、一致性、持久性的实现原理
  26. CDN请求过程详解
  27. 常用缓存技巧
  28. 如何高效对接第三方支付
  29. Gin框架简洁版
  30. InnoDB锁与事务简析
  31. 算法总结

读书笔记

  1. 原则
  2. 资治通鉴
  3. 敏捷革命
  4. 如何锻炼自己的记忆力
  5. 简单的逻辑学-读后感
  6. 热风-读后感
  7. 论语-读后感
  8. 孙子兵法-读后感

思考

  1. 为动员一切力量争取抗战胜利而斗争
  2. 反对自由主义
  3. 实践论
  4. 评价自己的标准
  5. 服务端团队假期值班方案
  6. 项目流程管理
  7. 对项目管理的一些看法
  8. 对产品经理的一些思考
  9. 关于程序员职业发展的思考
  10. 关于代码review的思考
  11. Markdown编辑器推荐-typora