在Go中封装平台特定代码的正确方法是什么?

Rob*_*bin 5 architecture cross-platform go

我想开发一个小型Go应用程序,该应用程序向演示文稿的受众显示使用的按键快捷方式。

为了了解键盘事件,我将必须使用一些平台特定的代码。封装平台特定代码的Go方法是什么?我一直在寻找诸如编译器切换器或平台模块之类的关键字,但实际上找不到任何相关信息。

icz*_*cza 5

平台特定代码的解决方案是构建约束

构建约束,也称为构建标记,是开始的行注释

// +build
Run Code Online (Sandbox Code Playgroud)

列出了将文件包含在软件包中的条件。约束可能会出现在任何类型的源文件中(不仅是Go),但它们必须出现在文件顶部附近,并且只能出现空白行和其他行注释。这些规则意味着在Go文件中,构建约束必须出现在package子句之前。

因此,基本上每个平台特定的Go代码都应该放入不同的文件中,并且您可以将这些Go文件中的每个标记为目标文件。

例如,如果文件包含Linux特定代码(例如syscalls),请使用以下命令启动它:

// +build linux
Run Code Online (Sandbox Code Playgroud)

如果文件包含Windows特定的系统调用,请使用以下命令启动它:

// +build windows
Run Code Online (Sandbox Code Playgroud)

还有更多“选项”可用,请阅读链接的文档。例如,您可以指定对OS,体系结构,Go版本以及所使用的编译器的约束。您还可以指定将使用逻辑OR或AND解释的多个约束,或者可以使用否定(例如,此代码适用于除Linux之外的每个目标平台)。

您甚至.go可以通过以下约束将文件标记为要忽略:

// +build ignore
Run Code Online (Sandbox Code Playgroud)

请注意,构建约束是编译器特定的。如果特定的编译器无法识别构建约束,则编译器将忽略该文件。例如,Go AppEngine SDK带有一个内置的,经过修改的Go编译器,该编译器还可以识别

// +build appengine
Run Code Online (Sandbox Code Playgroud)

约束,这意味着源文件仅适用于Google App Engine平台。“常规” Go编译器将忽略该文件,如果有人尝试在没有Go AppEngine SDK的情况下构建代码,则可能不会出现一堆编译器错误。


cat*_*cat 5

虽然@icza 的答案绝对是 OP 关于条件编译问题的正确权威答案,但在这种特定情况下,更简单的方法可能是值得的。

Go 是一种旨在在每个平台上编译相同(使用相同编译器)的语言,以鼓励跨平台代码和库重用。Go 不是 C/C++,因此必须花费时间来编写明确的跨平台代码。

当然,平台不可知性仅适用于 Go 的运行时,并且您正在尝试捕获按键,为此没有真正的单一平台不可知的解决方案。

因此,我对这个用例的更简单的建议类似于以下内容:

package main

import (
    "runtime"
    kp "kplib"
)

func main () {
    switch runtime.GOOS {
    case "windows":
        kp.WinKey()
    case "darwin":
        kp.MacKey()
    case "linux":
        kp.UnixKey()
    default:
        kp.TryKey()
    }
}
Run Code Online (Sandbox Code Playgroud)

有了隐含的保证,假设kplib将在任何地方编译(只需确保在给定平台上调用正确的方法!)。