英文:
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:
答案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)
答案5
得分: 1
我刚刚在寻找其他内容时偶然发现了这个帖子的年龄,所以我会添加一个更新的补充。如果你只是想处理正确的文件路径,我建议使用filepath.Join()。它可以消除所有与操作系统相关的猜测。如果你需要更多的内容,除了文件路径之外,可以使用运行时常量(runtime.GOOS
和runtime.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's no solution or workaround up to now, the most you can do is change your editor'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(".")) // 输出: .
}
- path - 标准库
或者使用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 (
"fmt"
"path/filepath"
)
// Calling main
func main() {
fmt.Println(filepath.Join("/", "/")) // out: /
fmt.Println(filepath.Join(""))// out:
fmt.Println(filepath.Join("dirname", "dirsubname")) // out: dirname/subdirname
fmt.Println(filepath.Join(".")) // out: .
}
- path - Standard library
Or use GOOS
:
os := runtime.GOOS
switch os {
case "windows":
fmt.Println("Windows")
case "darwin":
fmt.Println("MAC operating system")
case "linux":
fmt.Println("Linux")
default:
fmt.Printf("%s.\n", os)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论