如何在 Go 中可靠地检测操作系统/平台

Posted

技术标签:

【中文标题】如何在 Go 中可靠地检测操作系统/平台【英文标题】:How to reliably detect os/platform in Go 【发布时间】:2013-11-19 18:52:17 【问题描述】:

这是我目前正在使用的,我认为它可以完成工作,但必须有更好的方法:

func isWindows() bool 
    return os.PathSeparator == '\\' && os.PathListSeparator == ';'

如您所见,就我而言,我只需要知道如何检测窗口,但我想知道检测任何平台/操作系统的方法。

播放:

http://play.golang.org/p/r4lYWDJDxL

【问题讨论】:

当前版本的 Windows 可以使用 Posix 分隔符(即“/”)正常运行。对于 bat 脚本和旧的非 Posix 版本的 Windows,您只需要反斜杠。 你能定义“当前”吗?在过去的几周里,我被硬编码“/”烧死了…… Windows 95、98 ME 和所有早期版本都需要反斜杠。 Windows 2000、NT 和更高版本接受反斜杠和正斜杠作为等效项。反斜杠提供与旧版本的兼容性,而正斜杠提供 Posix 合规性。 感谢@Rick-777 的澄清。 【参考方案1】:

编译时检测

如果您这样做是为了根据操作系统有不同的实现,则更有用的是 具有具有该功能实现的单独文件,并为每个文件添加构建标签 的文件。这在标准库中的许多地方都有使用,例如in the os package。

这些所谓的“构建约束”或“构建标签”解释为here。

假设您有常量 PATH_SEPARATOR 并且您希望依赖于平台,您 会生成两个文件,一个用于 Windows,一个用于 (UNIX) 其余文件:

/project/path_windows.go
/project/path_unix.go

这些文件的代码将是:

path_windows.go

// +build windows

package project

const PATH_SEPARATOR = '\\'

path_unix.go

// +build !windows

package project

const PATH_SEPARATOR = '/'

您现在可以在代码中访问 PATH_SEPARATOR 并使其依赖于平台。

运行时检测

如果要在运行时确定操作系统,请使用runtime.GOOS 变量:

if runtime.GOOS == "windows" 
    fmt.Println("Hello from Windows")

虽然它被编译到运行时,因此忽略了环境, 但是,您可以相对确定该值是正确的。 原因是每个值得区分的平台都需要 由于不同的可执行格式而重建,因此具有新的GOOS 值。

【讨论】:

我试图运行它,但我得到了一些奇怪的错误。 path_windows.go:4:24: PATH_SEPARATOR 在此块中重新声明。 path_unix.go:4:24 的先前声明而我就是不明白...编译器不明白吗? @RamonJ.A.Smit 你需要像这样向这些文件添加构建约束:path_unix.go 应该有 // +build !windows 和 path_windows.go 应该有 // +build windows。我编辑了上面的答案以显示他们应该去哪里。它们必须出现在 package 语句之前,并且后跟一个空行,因此它们不会被解释为包的文档。 感谢您的额外意见!会玩这个。谢谢:-) @TimLewis 无论出于何种原因,我都无法让它工作。我在 Windows 上,我在 data_windows.go 中的 GetData 函数被“重新声明”,因为 data_unix.go 中的 GetData。在 package 语句之前和之后的空行都具有适当的构建约束(data_windows.go 具有 +build windowsdata_unix.go 具有 +build !windows),但它仍然不起作用。有什么想法吗? 哦,我明白了问题所在,我的命令是 go build -o ... cli/*.go,因此它正在构建所有 go 文件,而不管构建约束如何。我把它改成了go build -o ... ./cli,它起作用了。【参考方案2】:

你看过运行时包吗?它有一个 GOOS 常量:http://golang.org/pkg/runtime/#pkg-constants

【讨论】:

GOOS,在运行时包中,在编译时设置,无需安装 Go 工具即可读取。 @Matt 您正在考虑环境变量。 @Tyler 是 runtime.GOOS 的东西,它可以正常工作,例如:play.golang.org/p/0dDIEoFXfx【参考方案3】:

我只是偶然发现了这个寻找别的东西,并注意到这篇文章的年龄,所以我会添加一个更新的补充。如果您只是想处理正确的文件路径,我会使用filepath.Join()。它消除了操作系统问题的所有猜测。如果您需要更多内容,而不仅仅是文件路径,则可以使用运行时常量(runtime.GOOSruntime.GOARCH):playground example

【讨论】:

【参考方案4】:

由于这是一个较旧的问题和答案,我找到了另一个解决方案。

您可以简单地使用os 包中定义的常量。此 const 返回 rune,因此您还需要使用字符串转换。

string(os.PathSeparator)
string(os.PathListSeparator)

示例:https://play.golang.org/p/g6jnF7W5_pJ

【讨论】:

这个答案没有显示如何检测平台。本题使用 os.PathSeparator 和 os.PathListSeparator 来检测 Windows。【参考方案5】:

我在 Go 1.17.1 中进行了测试,它确实对我有用。

package main

import (
        "fmt"
        "runtime"
)
func main()
        fmt.Println(runtime.GOOS)


Output:
darwin

【讨论】:

同样的答案在这里:***.com/a/19847766/1517394【参考方案6】:

关于检测平台,您可以使用Distribution Detector project 来检测正在运行的Linux 发行版。

【讨论】:

以上是关于如何在 Go 中可靠地检测操作系统/平台的主要内容,如果未能解决你的问题,请参考以下文章

探索如何更可靠地运行Kubernetes

go语言简介

在php中检测浏览器、版本和平台的可靠方法

如何可靠地检测 iOS 9 上是不是连接了外部键盘?

如何“爆破检测”加密密码字段和存在验证码的Web系统

如何在软件中可靠地生成以太网帧错误?