runtime.goos返回编译时确定的静态操作系统标识(如"linux"、"windows"、"darwin"),非运行时探测,稳定且无开销;它与goarch独立,仅表示系统大类,不反映实际运行环境。

用 runtime.GOOS 判断当前操作系统类型
Go 编译时就确定了目标操作系统,运行时通过 runtime.GOOS 获取静态字符串(如 "linux"、"windows"、"darwin"),不是靠探测系统调用,所以稳定且无性能开销。
注意它和 GOARCH 是独立的:同一系统可能有不同架构(如 darwin/arm64 和 darwin/amd64),但 GOOS 只管系统大类。
- 常见值:
"linux"、"windows"、"darwin"、"freebsd"、"openbsd" - 不推荐用
os.Getenv("OS")或执行uname命令——不可靠,且跨平台行为不一致 - 别在
init()里依赖GOOS做全局变量初始化,除非你确认所有平台路径/权限逻辑都兼容
文件路径分隔符必须用 filepath.Join 而非字符串拼接
硬写 "/" 或 "\" 在 Windows 上会失败,Linux/macOS 上也可能因挂载点含反斜杠出问题。Go 的 filepath 包自动适配 GOOS。
比如构造配置路径:filepath.Join(os.Getenv("HOME"), ".myapp", "config.json") 在 Windows 返回 C:Users
ame.myappconfig.json(如果 HOME 被设为该路径),在 Linux 返回 /home/name/.myapp/config.json。
-
filepath.Separator是 rune 类型,不是字符串,不能直接用于strings.Split;要用filepath.ToSlash转成正斜杠再处理 - 读取用户传入的路径时,先用
filepath.Clean规范化,避免"../"绕过目录限制 - 不要用
path.Join替代filepath.Join——path是纯 URL/URI 风格,不处理驱动器盘符或 Windows 特殊路径
系统命令调用要按 GOOS 分支选择可执行文件名和参数
同一个工具在不同系统上可能名字不同(如 ls vs dir)、参数不兼容(如 ps -eo 在 macOS 不支持 -o)、甚至根本不存在(systemctl 仅 Linux)。
更稳妥的做法是封装一层抽象,例如进程检查:Linux 用 ps -p PID -o pid=,macOS 用 kill -0 PID 2>/dev/null,Windows 用 tasklist /FI "PID eq PID" /FO CSV 2>NUL。
- 避免直接拼接命令字符串,用
exec.Command的参数切片传参,防止 shell 注入 - 检查
cmd.Run()的*exec.ExitError,而不是只看err != nil——某些命令(如kill -0)失败时也返回非零退出码但不算错误 - 若需调用外部二进制,优先查
PATH(用exec.LookPath),而非硬编码路径(如/bin/ps)
权限与信号处理在 Windows 上必须降级或绕过
Windows 没有 Unix-like 的文件权限位、POSIX 信号(SIGINT、SIGHUP)、fork 或 setuid,强行移植会导致 panic 或静默失败。
例如监听 os.Interrupt(对应 Ctrl+C)在所有平台都有效,但 syscall.SIGUSR1 在 Windows 根本不存在;又如 os.Chmod 对 Windows 文件的“只读”属性只是模拟,无法控制 ACL。
- 用
build tags隔离平台专属代码,比如//go:build windows+// +build windows,比运行时if runtime.GOOS == "windows"更安全——编译期就排除非法调用 - 涉及服务管理(启停后台进程)、文件锁(
flock)、socket 选项(SO_REUSEPORT)等功能,Windows 必须提供 fallback 实现或明确报错 - 测试时别只跑 Linux 容器,CI 中至少加一个 Windows runner,否则
filepath.EvalSymlinks这类函数在符号链接处理上的差异会漏掉
/tmp 总是可写、os.Getwd() 返回绝对路径、或者把 os.RemoveAll 当作原子操作。这些地方得逐个对齐各平台文档,而不是靠试错。











