How to reliably detect os/platform in Go

huangapple go评论162阅读模式
英文:

How to reliably detect os/platform in Go

问题

以下是我翻译好的内容:

这是我目前正在使用的代码,我认为它能完成任务,但应该有更好的方法:

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

如你所见,在我的情况下,我只需要知道如何检测Windows,但我想知道检测任何平台/操作系统的方法。

Play链接:

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

英文:

Here's what I'm currently using, which I think gets the job done, but there's got to be a better way:

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

As you can see, in my case all I need to know is how to detect windows but I'd like to know the way to detect any platform/os.

Play:

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

答案1

得分: 193

在编译时进行检测

如果你这样做是为了根据操作系统有不同的实现,那么更有用的方法是将具有该特性实现的代码放在不同的文件中,并为每个文件添加构建标签。标准库中的许多地方都使用了这种方法,例如os包中

这些所谓的“构建约束”或“构建标签”在这里有解释。

假设你有一个常量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值。

英文:

Detection at compile time

If you're doing this to have different implementations depending on the OS, it is more useful to
have separate files with the implementation of that feature and add build tags to each
of the files. This is used in many places in the standard library, for example in the os package.

These so-called "Build constraints" or "Build tags" are explained here.

Say you have the constant PATH_SEPARATOR and you want that platform-dependent, you
would make two files, one for Windows and one for the (UNIX) rest:

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

The code of these files would then be:

path_windows.go

// +build windows

package project

const PATH_SEPARATOR = '\\'

path_unix.go

// +build !windows

package project

const PATH_SEPARATOR = '/'

You can now access PATH_SEPARATOR in your code and have it platform dependant.

Detection at runtime

If you want to determine the operating system at runtime, use the runtime.GOOS
variable:

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

While this is compiled into the runtime and therefore ignores the environment,
you can nevertheless be relatively certain that the value is correct.
The reason for this is that every platform that is worth distinguishing needs
rebuilding due to different executable formats and thus has a new GOOS value.

答案2

得分: 23

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

英文:

Have you looked at the runtime package? It has a GOOS const: http://golang.org/pkg/runtime/#pkg-constants

答案3

得分: 10

这是翻译好的内容:

现在是2022年,对于go 1.18+的正确答案是:

在运行时,你可以使用以下代码来判断操作系统是否为Windows:

if runtime.GOOS == "windows" {
  // 这里是Windows特定的代码...
}

如果你需要确定文件系统路径分隔符字符,可以使用os.PathSeparator

示例:

  • c:\program files
  • /usr/local/bin

如果你需要获取PATH环境变量中使用的路径列表分隔符,可以使用os.PathListSeparator

示例:

  • /usr/local/bin:/usr/local:
  • "C:\windows";"c:\windows\system32";
英文:

It's 2022 and the correct answer for go 1.18+ is:

At runtime you want:

if runtime.GOOS == "windows" {
  // windows specific code here...
}

If you need to determine the filesystem path separator character

Use: os.PathSeparator

Examples:
> - c:\program files
> - /usr/local/bin

If you need the Path List separator as used by the PATH environment variable

Use: os.PathListSeparator

Examples:
> - /usr/local/bin:/usr/local:
> - "C:\windows";"c:\windows\system32";

答案4

得分: 2

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

你可以直接使用 os 包中定义的常量。这些常量返回一个 rune 类型,所以你需要进行字符串转换。

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

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

英文:

Since this is an older question and answer I have found another solution.

You could simply use the constants defined in the os package. This const returns a rune so you would need to use string conversion also.

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

Example: https://play.golang.org/p/g6jnF7W5_pJ

答案5

得分: 1

我刚刚在寻找其他内容时偶然发现了这个帖子的年龄,所以我会添加一个更新的补充。如果你只是想处理正确的文件路径,我建议使用filepath.Join()。它可以消除所有与操作系统相关的猜测。如果你需要更多的内容,除了文件路径之外,可以使用运行时常量(runtime.GOOSruntime.GOARCH):playground示例

英文:

I just stumbled on this looking for something else and noticed the age of this post so I'll add a more updated addition. If you're just trying to handle the correct filepath I would use filepath.Join(). Its takes all of the guesswork out of os issues. If there is more you need, other than just filepath, using the runtime constants (runtime.GOOS & runtime.GOARCH) are the way to go: playground example

答案6

得分: 1

我在Go 1.17.1中进行了测试,对我来说确实有效。

package main

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

输出
darwin
英文:

I tested in Go 1.17.1 which really worked for me.

package main

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

Output:
darwin

</details>



# 答案7
**得分**: 0

关于检测平台,你可以使用[Distribution Detector项目][1]来检测正在运行的Linux发行版。

[1]: https://github.com/dekobon/distro-detect/

<details>
<summary>英文:</summary>

With regards to detecting the platform, you can use [Distribution Detector project][1] to detect the Linux distribution being run.


  [1]: https://github.com/dekobon/distro-detect/

</details>



# 答案8
**得分**: 0

@nemo的第一个答案是最合适的,我只是想指出,如果你目前是**gopls**语言服务器的用户,那么**构建标签**可能无法按预期工作。

目前还没有解决方案或解决方法,你能做的最多就是更改编辑器的lsp配置(如vscode、neovim、emacs等),选择一个构建标签,以便能够在不出错的情况下编辑带有该标签的文件。
使用其他标签编辑文件将无法正常工作,尝试选择多个标签也会失败。
这是该问题的当前进展[github@go/x/tools/gopls][1]


  [1]: https://github.com/golang/go/issues/29202

<details>
<summary>英文:</summary>

The first answer from @nemo is the most apropiate, i just wanted to point out that if you are currently a user of **gopls** language server the **build tags** may not work as intended.

There&#39;s no solution or workaround up to now, the most you can do is change your editor&#39;s lsp configs (vscode, neovim, emacs, etc) to select a build tag in order to being able to edit the files with that tag without errors.
Editing files with another tag will not work, and trying to select multiple tags fails as well.
This is the current progress of the issue [github@go/x/tools/gopls][1]


  [1]: https://github.com/golang/go/issues/29202

</details>



# 答案9
**得分**: 0

使用`path`包:
```go
package main

// 导入 fmt 和 path/filepath 包
import (
    "fmt"
    "path/filepath"
)

// 调用 main 函数
func main() {
    fmt.Println(filepath.Join("/", "/")) // 输出: /
    fmt.Println(filepath.Join("")) // 输出: 
    fmt.Println(filepath.Join("dirname", "dirsubname")) // 输出: dirname/subdirname
    fmt.Println(filepath.Join(".")) // 输出: .
}

或者使用GOOS

os := runtime.GOOS
switch os {
case "windows":
    fmt.Println("Windows")
case "darwin":
    fmt.Println("MAC 操作系统")
case "linux":
    fmt.Println("Linux")
default:
    fmt.Printf("%s.\n", os)
}
英文:

Use path:

package main
  
// Importing fmt and path/filepath
import (
    &quot;fmt&quot;
    &quot;path/filepath&quot;
)
  
// Calling main
func main() {
    fmt.Println(filepath.Join(&quot;/&quot;, &quot;/&quot;)) // out: /
    fmt.Println(filepath.Join(&quot;&quot;))// out: 
    fmt.Println(filepath.Join(&quot;dirname&quot;, &quot;dirsubname&quot;)) // out: dirname/subdirname
    fmt.Println(filepath.Join(&quot;.&quot;)) // out: .
  
}
  • path - Standard library

Or use GOOS:

os := runtime.GOOS
    switch os {
    case &quot;windows&quot;:
        fmt.Println(&quot;Windows&quot;)
    case &quot;darwin&quot;:
        fmt.Println(&quot;MAC operating system&quot;)
    case &quot;linux&quot;:
        fmt.Println(&quot;Linux&quot;)
    default:
        fmt.Printf(&quot;%s.\n&quot;, os)
    }

huangapple
  • 本文由 发表于 2013年11月8日 06:02:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/19847594.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定