go generate介绍及使用


最近公司需要将状态码快速转成语言包,又想在makefile执行是一次性执行。随即用到了go generate并记录。

介绍

go generate命令是go 1.4版本里面新添加的一个命令,当运行go generate时,它将扫描与当前包相关的源代码文件,找出所有包含"//go:generate"的特殊注释,提取并执行该特殊注释后面的命令,命令为可执行程序,形同shell下面执行。

使用场景

在有些场景下,我们会使用go generate:

  • 在build之前生成一些特定文件(下文介绍)
  • yacc:从 .y 文件生成 .go 文件.
  • protobufs:从 protocol buffer 定义文件(.proto)生成 .pb.go 文件。
  • Unicode:从 UnicodeData.txt 生成 Unicode 表.

注意事项

  • 必须在.go源码文件中
  • 每个源码文件可以包含多个generate特殊注释时
  • 显示运行go generate命令时,才会执行特殊注释后面的命令
  • 如果前面的注释执行出错,则种植执行

使用

环境变量

在使用go generate时,有一些环境变量可以使用:

$GOARCH
    体系架构 (arm、amd64等)
$GOOS
    OS环境(linux、windows等)
$GOFILE
    当前处理中的文件名
$GOLINE
    当前命令在文件中的行号
$GOPACKAGE
    当前处理文件的包名
$DOLLAR
    美元符号

执行方法

假设有一个main.go文件,内容如下:

package main

import "fmt"

//go:generate echo hello
//go:generate go run main.go
//go:generate  echo file=$GOFILE pkg=$GOPACKAGE
func main() {
    fmt.Println("Hello world!")
}

命令行执行 go gennerate之后,输出如下:

$ go generate
hello
Hello world!
file=main.go pkg=main

实例

将 code.go 中状态码对应的 const 注释转换成 .yaml 格式文件。
ps :不知道官方有没有转换的包,用笨办法写了一个脚本文件。

文件结构

如图:

  • changeToolForCode :用go写的脚本文件
  • code.go:定义状态码
  • language_pkg.yaml:存放状态码对应的翻译内容

代码内容

code.go文件:

package test

//go:generate changeToolForCode "./code.go" "./language_pkg.yaml" resp
const (
    FAILED           Code = -1     // 失败
    SUCCESS          Code = 0      // 成功
    ReqArgsErr       Code = 100400 // 请求参数错误信息
    SaveRecordFailed Code = 100500 // 后台存储记录失败
)

changeToolForCode 脚本内容:

#!/usr/bin/env gosl

import "fmt"
import "strings"
import "bufio"
import "io/ioutil"
import "os"

if len(os.Args) != 4 {
    fmt.Println("请检查输入的读取文件写入文件路径,以及所需要的")
    fmt.Println("..changeTool  <readPath> <writePath> <name>")
}

var strs []string

//命令行传入读取文件
file_bytes, err := ioutil.ReadFile(os.Args[1])
if err != nil {
    fmt.Println(err.Error() + "\n")
    return
}

//按行读取
lines := strings.Split(string(file_bytes), "\n")

//根据 = 进行切割 ,判断 = 右边有没有//字串,之后进行切割组合
for _, line := range lines {
    items := strings.Split(string(line), "=")
    for _, item := range items {
        if strings.Contains(item, " //") {
                items := strings.Split(string(item), " //")
                items[0] = strings.Replace(items[0], " ", "", -1)
                items[1] = strings.Replace(items[1], " ", "", -1)
                
                str := "  " + items[0] + ": " + "\"" + items[1] + "\""
                strs = append(strs, str)
        }
    }
}

// 打开命令行传入的文件,进行追加内容
f, err := os.OpenFile(os.Args[2], os.O_CREATE|os.O_APPEND|os.O_RDWR, 0660)
if err != nil {
    fmt.Printf(err.Error() + "\n")
    return
    
}

defer f.Close()

w := bufio.NewWriter(f)

fmt.Fprintln(w, "\n"+os.Args[3]+":")
for _, str := range strs {
    fmt.Fprintln(w, str)
}

w.Flush()

fmt.Println("success")

运行go generate

单个运行只需要在对应目录(包)下执行:

go generate

即可。
对应有多个目录,且又有多个generate需要执行的,在最上层目录下运行:

go generate ./...

即可遍历所有目录并执行(注意不能出错)。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值