go 编译选项、伪指令、代码生成简介

本文介绍了Go语言在构建过程中如何通过编译选项、链接选项和编译器伪指令实现个性化定制,如-noinline防止函数内联,-linkname导出未导出的变量,以及-cgo在C代码集成中的应用。同时,文章还探讨了代码生成机制,包括//go:generate注释触发的命令执行,以及在生成命令中可用的环境变量。
摘要由CSDN通过智能技术生成


  golang 是易用的,在构建代码时,go 程序为我们自动完成对 compile、link 工具的配合调用流程,构建命令十分简单,形如:

  go build [-o output] [build flags] [packages]

  golang 易用的同时,也保留了一定的灵活性,如通过 [build flags] 对编译、链接过程做个性化定制。

1 build flags

  • -gcflags
    向 go tool compile 传递 编译选项 列表,各选项用空格分开
  • -ldflags
    向 go tool link 传递 链接选项 列表,各选项用空格分开
  • -x
    打印构建过程中调用的命令
  • -n
    打印构建过程中调用的命令,但不执行它们
  • -a
    即使可执行文件已经是最新的,也强制执行重新构建的过程
  • -work
    打印并保留构建过程的临时目录

2 编译选项

  • -m
    打印编译器所做的优化
  • -N
    禁止优化
  • -l
    禁止内联
  • -race
    编译过程中做竞态检测
  • -e
    清除报错数量上限,默认是10
  • -h
    遇到第一个错就停止,并打印堆栈

3 编译器伪指令

  编译选项是针对所有 go 文件生效的,控制粒度比较粗。go 提供了另一种在代码行级别干预编译器行为的方式,即编译器伪指令(Compiler Directives)。这种机制有点类似 gcc 的 attribute。编译器伪指令以注释的形式写在代码中,形如 //go:directive

noinline

  写在函数定义前一行,确保这个函数不被内联调用。优先级高于编译选项指定的规则。

//go:noinline
	func DonnotInlineMe(){
}

linkname

  linkname 用于把在一个未导出的变量或函数,导出到一个指定的包中(从而可在定义包外部引用)。由于 linkname 颠覆了包的模块化规则,所以需要引入 unsafe 包 import _ "unsafe" 才能使用。

使用格式:
//go:linkname localname [importpath.name]

// A/f.go
package A;
func af(){
}
// B/f.go
package B;
//go:linkname Af B.af
func Af()

4 链接选项

  • -X importpath.name=value
    初始化变量值
  • -buildmode mode
    构建模式,如 exe(默认)/plugin(动态链接库)/c-archive
  • -s
    删除符号表、调试信息
  • -w
    删除 DWARF 符号表
  • -E entry
    指定程序入口符号

5 cgo 选项

  当 go 构建 c 代码时,可以通过多种方式传递编译选项给 c 编译器:

  • 选项写在 c 代码注释中
    • 编译 // #cgo CFLAGS:
    • 链接 // #cgo LDFLAGS:
  • 选项定义在环境变量中
    • 编译 export CGO_CFLAGS=
    • 链接 export CGO_LDFLAGS=

6 代码生成

  在 go 文件中以注释的形式 //go:generate cmd 声明对 shell 命令 cmd 的调用。我们称这个 cmd 为 生成命令。通常在 go build 前,先执行一次 go generate 触发 生成命令 执行,来做具体的代码生成工作。

6.1 设置生成命令别名

// src.go
// 声明 cmd [parameters] 命令别名为 aliasCmd 
//go:generate -command aliasCmd cmd [parameters]

// 调用命令 aliasCmd
//go:generate aliasCmd

  执行 go generate src.go 则触发执行 cmd [parameters] 命令,cmd 即可以是单纯的 shell 命令,也可以是执行某个 shell 脚本。

6.2 生成命令中可用的环境变量

  • $GOFILE
    文件名,不包含路径和扩展名

  • $GOLINE
    //go:generate cmd 在文件中的行号

  • $GOPACKAGE
    包名,含完整路径

  • $GOOS
    操作系统名,如 windows, linux 等

参考

cmd: go build
cmd: go tool compile
cmd: go tool link
cmd: cgo
cmd: go generate
https://go.dev/blog/generate
https://learnku.com/go/
gcc attribute syntax

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

游戏AI开发者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值