我在暴躁同事小张的胁迫下学会了Go的交叉编译和条件编译

今天继续关于

go

开发经验的分享,这次的主题是关于

go

的交叉编译和条件编译,伴随着我对自己打不过、惹不起的壕同事小张还有运维们的碎碎念。

交叉编译

交叉编译是用来在一个平台上生成另一个平台的可执行程序。比如我工作开发时用的Mac,系统内核是

darwin

,小张用的是外星人,系统内核是

windows

(小张明显比我有钱,我的Mac是公司发的,人家的外星人是为打游戏自己买的)。

那么假如我编写的代码依赖了系统底层平台或处理器架构特性的

go

包时,比如说我上周在文章《Go服务迁到K8s后老抽风重启? 记一次完整的线上问题解决过程》里写的,为了把

go

运行时的

panic

错误重定向到日志文件,我用了

syscall.Dup2

这个函数把标准错误原来的文件描述符替换成了自己指定的日志文件的描述符。

syscall.Dup2

go

语言在类

Unix

系统,

X86_64

架构下才有的函数库,在Mac系统上、各种服务器环境上编译都没有问题,但是唯独在像小张这样不用办公电脑的土豪们用的

windows

系统上编译不过去。

所以在上篇文章说的那个为了追踪在

Kubernetes

上服务老重启的问题,用

syscall.Dup2

重定向标准输出的解决方案是有副作用的,我贴一下之前这个功能的代码。

代码语言:javascript代码运行次数:0运行复制

func RewriteStderrFile() error {   if runtime.GOOS == "windows" {      return nil   }   ......    file, err := os.OpenFile(stdErrFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)    if err != nil {      fmt.Println(err)        return err    }        if err = syscall.Dup2(int(file.Fd()), int(os.Stderr.Fd())); err != nil {        fmt.Println(err)        return err    }    ......    return nil}

天真的用了一个runtime.GOOS == "windows"的判断,我还想着能在代码里根据内核的不同执行不同的代码,但是

go

的软件包是先编译成可执行文件再执行的,这个判断根本没啥用。所以在

windows

系统下编译项目的时候,因为没有

syscall.Dup2

直接就失败了......。

我这不就是典型的动态语言的思维吗,之前还写文章跟别人讲《如何避免用动态语言的思维写Go代码》......这次打自己脸打的实在有点疼。

虽然项目这个更新已经上线了,但是土壕小张和运维我都惹不起,迫于无奈我就看了看

go

官方的标准库到底是怎么兼容多平台的。

条件编译

我发现在go的每个内置库里都有很多以不停系统名结尾的文件。下面是

go

的os[1]内置库源代码的部分截图:

我在暴躁同事小张的胁迫下学会了Go的交叉编译和条件编译

在有些文件里还有类似下面这样的注释:

代码语言:javascript代码运行次数:0运行复制

// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solarispackage os...

看了些资料后才知道,他们是用于

go

软件包的条件编译[2]的,条件编译的意思就是通过某种方式来指示编译器编译特定代码。

go

不支持宏,不可以像c语言那样使用

#define

来控制是否包含平台相关的特定代码。作为替代,

go

使用构建标签(

build tags

)和代码文件的命名约定来支持

go

软件包的条件编译。

构建标签

构建标签就是上面我说的源代码里的注释:

代码语言:javascript代码运行次数:0运行复制

// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solarispackage os...

需要注意的是,构建标签必须在代码文件里位于

package

声明的上方,并且后跟一个空行。

go

编译一个包时,它会分析包内的每个源码文件并查找构建标签。标签决定了这个源码文件是否被编译。

构建标签遵循以下三个原则:

空格隔开的选项是或(OR)的关系逗号隔开的选项是与(AND)的关系每个选项由字母和数字组成。如果前面加上

!

,则表示反义代码语言:javascript代码运行次数:0运行复制

// +build darwin freebsd netbsd openbsd

上面的例子,表示这个源码文件只会在支持

kqueue

BSD

系统中被编译。

一个源码文件可以包含多个构建标签。构建规则是每个独立规则的逻辑与关系。如下例子表示该文件将在

linux/386

darwin/386

平台才会被编译 。

代码语言:javascript代码运行次数:0运行复制

// +build linux darwin// +build 386

用逻辑表达式表示就是:(linux OR darwin) AND 386。

文件名后缀

第二种条件编译的方法是通过源码文件的文件名实现的。这种方案比构造标签方案更简单。

go/build包的文档有关于命名约定的描述。简单来说,如果文件名包含_GOOS.go后缀,那么这个源码文件只会在对应的平台被编译。其他平台会忽略这个文件。另一种约定是_GOARCH.go。这两种后缀可以组合起来,但要保证顺序,正确的格式是_GOOS_GOARCH.go,错误的格式是_GOARCH_GOOS.go。

Sudowrite Sudowrite

对用户最友好的AI写作工具

Sudowrite 169 查看详情 Sudowrite

以下是文件名后缀的一些例子:

代码语言:javascript代码运行次数:0运行复制

mypkg_freebsd_arm.go // 只在 freebsd/arm 系统编译mypkg_plan9.go       // 只在 plan9 编译mypkg_darwin.go      // 只在macos 系统编译

源码文件光有后缀是不行的,比如如下文件名:

代码语言:javascript代码运行次数:0运行复制

_linux.go_freebsd_386.go

即使是在Linux或FreeBSD系统,这两个文件也会被忽略,原因是

go/build

包会忽略所有文件名以

.

_

开始的文件。

使用构建标签还是文件名后缀

构建标签和文件名后缀在功能上是重叠的。比如,一个名为

mypkg_linux.go

的文件,再包含构建标签

// +build linux

会显得多余。

通常来说,当只有一个特定平台或体系需要指定时,我们选择文件名后缀的方式。比如:

代码语言:javascript代码运行次数:0运行复制

mypkg_linux.go         // 只在 linux 系统编译mypkg_windows_amd64.go // 只在 windows amd 64位 平台编译

相反,如果你的文件需要指定给多个平台或体系架构使用,或者你需要排除某个特定平台时,我们选择构建标签的方式。比如:

代码语言:javascript代码运行次数:0运行复制

// 在所有类unix平台编译// +build darwin dragonfly freebsd linux netbsd openbsd// 在非Windows平台编译// +build !windows

实践应用

应用环境,我就说下是怎么解决文章开头说的问题让小张大佬平复心情的吧......。

设置条件编译

首先我像下面这样,在包里建了两个源码文件,用来分别存放在

windows

系统和非

windows

系统下使用的

RewriteStderrFile

函数:

代码语言:javascript代码运行次数:0运行复制

project|└───pkg1│   │----rewrite_err_unix.go│   │----rewrite_err_windows.go

因为我们的项目在那几个大佬电脑的

windows

系统上编译和运行的时候都是开发阶段,其他测试上线之类的环境都是

Linux

系统,所以我懒癌发作,直接写了个空函数,毕竟只要能编译运行小张就不会太难为我了。

代码语言:javascript代码运行次数:0运行复制

//rewrite_err_windows.gopackage pkg1func RewriteStdErrLog(topic string) error { return nil}

对于要在服务器上和Mac电脑上编译的源码,跟之前的差不多,只是增加了构建标签:

代码语言:javascript代码运行次数:0运行复制

//+build darwin linuxpackage pkg1......func RewritePanicsToFile(topic string) error {    ......    file, err := os.OpenFile(stdErrFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)    if err != nil {      fmt.Println(err)        return err    }   if err = syscall.Dup2(int(errFileHandler.Fd()), int(os.Stderr.Fd())); err != nil {      return err   }    ......     return nil}

执行交叉编译

交叉编译的执行就非常简单了,在编译时给go build命令设置

OS

ARCH

参数即可:

比如在Mac 下编译

windows

64位可执行程序,用:

代码语言:javascript代码运行次数:0运行复制

CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go

在Mac系统执行完上面的命令就会编译生成软件包在Windows系统上的可执行文件(.exe文件)

如果是

windows

下编译 Mac 64位可执行程序,用:

代码语言:javascript代码运行次数:0运行复制

SET CGO_ENABLED=0SET GOOS=darwinSET GOARCH=amd64go build main.go

总结

事实上,除了用于

.go

的Go源码文件,构建标签和文件名后缀这些条件编译规则可以作用于任何go tool可以编译的源码文件,包括

.c

.s

文件。

go

标准库中,尤其是

runtime

syscall

OS

net

包中包含了大量这种例子。咱们一定要去看看,多学习,尤其是身边有像小张这样又壕又凶的队友的同学们,一定把今天我说的这些都学会......。

参考资料

[1]

os: https://github.com/golang/go/tree/master/src/os

以上就是我在暴躁同事小张的胁迫下学会了Go的交叉编译和条件编译的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/755223.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月25日 22:31:21
下一篇 2025年11月25日 22:31:47

相关推荐

  • 开发人员活动的前20个Altcoins:GitHub数据突出显示正在进行的创新

    尽管价格波动常常占据新闻头条,但加密货币项目的长期前景往往取决于其持续的技术发展和创新。 在快速变化的加密领域,虽然价格变动吸引了大部分关注,但真正决定项目未来的是开发团队不断推进技术边界的努力。 市场行情可以反映行业的短期经济状况,但如果想了解哪些项目正在引领技术创新,就需要深入研究GitHub等…

    2025年12月8日
    000
  • 币安的USDT怎么提现?TRC20和ERC20手续费差多少?

    币安 USDT 提现时,TRC20 网络手续费低于 ERC20。为确保安全高效提现,需先完成 KYC 验证、绑定正确地址,并了解 TRC20 基于波场、手续费低,ERC20 基于以太坊、手续费较高;操作步骤包括登录账户、进入资金页面、选择现货账户、点击 USDT 提现、正确选择网络类型(务必与接收地…

    2025年12月8日 好文分享
    000
  • ripplecoin采矿:目标云开采,使被动收入成为稳定增值的新选择

    当ripple分配2.3亿xrp引起了市场的关注时,理性的投资者涌向ripplecoin矿业:零阈值云采矿 我们的新闻是如何制作的 严格的编辑政策,侧重于准确性,相关性和公正性 Ad Dibleiamer Morbi Pretium Leo et nisl aliquam Mollis。 quisq…

    2025年12月8日
    000
  • 电脑怎么登录欧意?ouyi欧意交易所pc端安装包下载

    电脑登录欧意交易所,并下载欧意交易所PC端安装包,是进入数字货币交易世界的关键一步。想象一下,你坐在电脑前,准备开启你的数字货币交易之旅,却发现不知道如何登录欧意交易所,或者找不到PC端安装包的下载入口。这无疑会让你感到沮丧。别担心,本文将详细为你解答这些问题,让你轻松上手,畅游数字货币市场。我们将…

    2025年12月8日
    000
  • Pi Network 的 GCV 是什么?为什么大家都在谈论它?

    pi network 的 gcv 最近成为社区热议话题之一。有人认为它是通往巨额财富的钥匙,而另一些人则认为它纯粹是炒作。究竟是怎么回事?让我们来一探究竟。 Pi Network 的 GCV 是什么?为什么大家都在谈论它? 在 Pi Network 社区中,GCV 代表“全球共识价值”,这是 Pi …

    2025年12月8日
    000
  • Skatechain(SKATE)是什么?SKATE代币经济学与空投介绍

    目录 Skatechain 是什么?项目背景基础架构代币经济学代币供应代币用途SKATE代币空投计划 skatechain 的推出,不仅为开发者提供了一个可以同时在数千条链上运行应用的平台,还通过引入通用应用范围的概念,使得基本应用能够在所有链都可访问的共享池中进行集体开发和维护,从而确保了开发者和…

    2025年12月8日 好文分享
    000
  • 把美国打造成加密货币强国!川普上任后法规、监管进展盘点

    自2025 年1 月川普重回美国总统职位以来,美国加密货币监管环境有了巨大的改变,除了选前对加密货币的承诺一一兑现,上任后的行政命令、人事任命及监管机构态度的变化,再再都显示美国加密货币产业正进入一个新阶段。 这篇文章,就来盘点川普上任后美国加密货币监管环境的进展,从行政命令到法规松绑、SEC 对加…

    2025年12月8日
    000
  • 德意志银行正评估稳定币发行与RWA代币化存款应用

    德国最大的银行,德意志银行(Deutsche Bank AG)本周透露,正积极评估发行稳定币的选项,以及代币化存款的应用潜力。反映出随着监管框架逐步成熟,传统金融机构正加快数字化转型的步伐。 德意志银行的数字资产策略 德意志银行数字资产与货币转型部门主管Sabih Behzad在近期采访中表示,该银…

    2025年12月8日
    000
  • XRP价格预测:向上势头会继续吗?

    xrp当前交易价格为2.28美元,过去24小时内涨幅达4.60%,近一周内则上涨了5.97%。 目前XRP的价格保持在2.28美元,在过去一天中增长了4.60%,周涨幅达到5.97%。随着交易额攀升至22.4亿美元,增幅高达54.66%,显示出市场动能正在增强。 此外,加密货币分析师Viproset…

    2025年12月8日
    000
  • 保持支持,但阻力最终可以破解吗?

    cardano(ada)近期处于盘整状态,徘徊在约0.6622美元附近,当日小幅下滑0.51%。尽管如此,成交量显著降低,较前一日减少了近38%,降至3.6057亿美元。 过去一周内,ADA微跌不足1%,并持续在关键支撑位附近波动。支撑位能否坚守?阻力位又是否能突破? 据分析师Crypto Wink…

    2025年12月8日
    000
  • 加密股票股票比特币作为机构换档策略

    尽管比特币走势平稳,但与加密货币相关的股票再度强势崛起,表现超越大盘。据10倍研究发布的一份最新报告显示,公开交易的加密公司总市值已突破3000亿美元大关。 加密股票今年的表现优于比特币,这得益于监管环境的明朗化以及比特币的强劲走势,促使公共市场资金大量流入与加密基础设施相关的股票。 比特币(BTC…

    2025年12月8日
    000
  • 德意志银行探索稳定的存款

    德意志银行(deutsche bank)正着手研究稳定币(stablecoins)以及存款代币化的问题,显示出其对数字化融资领域的浓厚兴趣。据彭博社消息,该行正在讨论究竟是自行开发稳定币还是与其他行业内的稳定币项目展开合作。 彭博社指出,德意志银行正在考量是否要创建专属的稳定币或是参与到整个行业的稳…

    2025年12月8日
    000
  • UNISWAP(UNI)价格预测:2025–2030

    UNISWAP已成为分散金融(DEFI)生态系统的基石,提供了无信任的,点对点交易的经验 UNISWAP(加密:UNI)已成为分散金融(DEFI)生态系统的基石,提供了没有中介的无信任的,点对点的交易经验。它促进了大规模的链贸易量,并成为全球最具影响力的分散交易所(DEX)之一。在一个显着的成就中,…

    2025年12月8日
    000
  • 逃生学院2:后2学校

    在开发者数字展示日当天,iam8bit与cow crew游戏将首次公开亮相《逃脱学院2:重返校园》,这是备受赞誉的《逃脱学院》系列的续作。 在开发者数字展示日当天,IAM8BIT与COW CREW游戏将首次公开亮相《逃脱学院2:重返校园》,这是广受好评的《逃脱学院》的后续作品。原版游戏于2022年发…

    2025年12月8日
    000
  • 解码PI网络的全球共识值(GCV)概念

    PI Network是一个区块链项目,近年来引起了人们的重大关注,最近围绕着一个名为“全球共识价值(GCV)”的概念进行了激烈的讨论。 PI Network是一个区块链项目,近年来一直在引起浪潮,它围绕全球共识价值(GCV)的概念进行了一些激烈的讨论。在PI社区的成员中,GCV已成为一个流行语,在热…

    2025年12月8日
    000
  • Fartcoin Fartcoin/USD违反了更广泛的市场低迷

    fartcoin fartcoin/usd today saw a 4% gain defying the broader market downturn, outperforming major meme coins like dogecoin doge/usd and shiba inu shi…

    2025年12月8日
    000
  • 系绳投资于Shiga Digital来加强非洲的链链金融生态系统

    tether宣布对shiga digital进行战略投资,后者是一家专注于为非洲提供区块链驱动金融服务的金融科技公司。 Tether是稳定币USDT的发行方,此次投资旨在加强跨境交易能力,并为非洲的企业提供获取国际流动性的途径。 Shiga Digital提供的服务包括虚拟账户、场外交易(OTC)、…

    2025年12月8日
    000
  • Rails筹集了1400万美元,以在美国启动其混合加密货币交易平台

    由加拿大创立的迈阿密总部的铁轨项目通过销售代币筹集了1400万美元(约合1,910万加元),并推出了混合动力系统。 由加拿大开发的迈阿密试点铁路项目通过代币销售筹集了1400万美元(约合1,910万加元),并在美国推出了其混合加密货币交易平台(美国)。 “法规有时会成为创新的障碍,你必须在良好的监管…

    2025年12月8日
    000
  • 加密政策组织敦促国会在市场结构立法中包括软件开发人员保护

    由八个加密政策组织组成的小组敦促美国国会领导人通过将其包括在市场结构立法中,以支持一项最近重新引入的法案,以保护软件开发人员。 由八个加密政策组织组成的小组敦促美国国会领导人将《区块链监管确定性法》(BRCA)包括在市场结构立法中。 加密政策小组寻求软件开发人员的保护 加密政策组织,即DEFI教育基…

    2025年12月8日
    000
  • btc看盘软件官网地址 btc看盘软件官方网页版入口

    BTC看盘软件应运而生,它不仅仅是一款简单的行情查看工具,更是您在数字货币交易世界中的得力助手。该软件集成了实时行情数据、专业的图表分析、个性化的预警设置等功能,旨在帮助用户更高效、更理性地进行交易。无论您是经验丰富的资深交易员,还是初入币圈的新手,这款软件都能满足您不同的需求,让您在波澜壮阔的数字…

    2025年12月8日
    000

发表回复

登录后才能评论
关注微信