求助:Mac系统下unix.Mount未定义问题(Golang相关)
求助:Mac系统下unix.Mount未定义问题(Golang相关) 最近几天刚开始接触Go语言。
我在Ubuntu虚拟机上写了一些代码,编译和运行都很顺利。然后我决定在我的Mac工作站上进行开发,但同样的代码却无法编译。
出现以下错误:
./ds-as-mounter.go:57:9: undefined: unix.Mount
./ds-as-mounter.go:57:35: undefined: unix.MS_BIND
奇怪的是,unix.Unmount 却能正常使用。
我已经通过 go get -u golang.org/x/sys/unix 安装了unix包。
这是我的包开头部分:
package main
import (
"fmt"
"golang.org/x/sys/unix"
"os"
"regexp"
"sync"
)
//....
这里是调用Mount和Unmount的地方:
func mount(src, dest string, wg *sync.WaitGroup) {
defer wg.Done()
//fmt.Println("Mounting", src, dest)
err := unix.Mount(src, dest, "", unix.MS_BIND, "")
if err != nil {
fmt.Println(src, dest, err)
}
}
func unmount(dest string, wg *sync.WaitGroup) {
defer wg.Done()
//fmt.Println("Unmounting", dest)
err := unix.Unmount(dest, 0)
if err != nil {
fmt.Println("Unmount", dest, err)
}
}
需要注意的是,编译器报错的是 unix.Mount 和 unix.MS_BIND,而不是 unix.Unmount。
我感到很困惑。如有任何帮助将不胜感激。谢谢!
go version go1.11.2 darwin/amd64
更多关于求助:Mac系统下unix.Mount未定义问题(Golang相关)的实战教程也可以访问 https://www.itying.com/category-94-b0.html
mount 调用确实仅针对 Linux 系统实现。
这很合理,但我原本期望文档能反映这一点。
感谢您的帮助。
更多关于求助:Mac系统下unix.Mount未定义问题(Golang相关)的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
如果你在系统上执行 go doc 命令,它们确实会显示。不过在线文档是针对 Linux 生成的。
mount 调用确实仅在 Linux 系统中实现。
jb@kvin:~/g/s/g/x/s/unix $ git grep Mount\(
syscall_linux.go:func Mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
Unmount 在更多平台上得到了实现。如果让我推测,我会说 Unmount 之所以"简单",是因为它在各个系统上的行为大致相同。而另一方面,Mount 需要处理大量标志和选项,这些都与具体系统和文件系统密切相关。
例如,macOS 并不支持您尝试实现的绑定挂载功能,因此无法在此系统上实现该操作。
问题在于 golang.org/x/sys/unix 包在不同操作系统上的实现不同。在 macOS 上,unix.Mount 和 unix.MS_BIND 确实未定义,因为 macOS 使用不同的挂载机制(通过 syscall.Mount 实现)。
以下是解决方案:
1. 使用构建标签区分不同平台
创建两个文件,通过构建标签处理平台差异:
mount_linux.go(用于 Linux):
// +build linux
package main
import "golang.org/x/sys/unix"
func mount(src, dest string) error {
return unix.Mount(src, dest, "", unix.MS_BIND, "")
}
func unmount(dest string) error {
return unix.Unmount(dest, 0)
}
mount_darwin.go(用于 macOS):
// +build darwin
package main
import (
"syscall"
)
func mount(src, dest string) error {
// macOS 使用 syscall.Mount 和不同的标志
return syscall.Mount(src, dest, "", syscall.MS_BIND, "")
}
func unmount(dest string) error {
return syscall.Unmount(dest, 0)
}
2. 在主要代码中使用统一的函数调用
修改你的主文件:
package main
import (
"fmt"
"sync"
)
func mount(src, dest string, wg *sync.WaitGroup) {
defer wg.Done()
err := mount(src, dest)
if err != nil {
fmt.Println(src, dest, err)
}
}
func unmount(dest string, wg *sync.WaitGroup) {
defer wg.Done()
err := unmount(dest)
if err != nil {
fmt.Println("Unmount", dest, err)
}
}
3. 或者使用条件编译的常量定义
在同一个文件中处理:
package main
import (
"fmt"
"sync"
)
// 根据平台导入不同的包
// +build linux
import "golang.org/x/sys/unix"
// +build darwin
import "syscall"
func mount(src, dest string, wg *sync.WaitGroup) {
defer wg.Done()
var err error
// 根据平台使用不同的挂载函数
// +build linux
err = unix.Mount(src, dest, "", unix.MS_BIND, "")
// +build darwin
err = syscall.Mount(src, dest, "", syscall.MS_BIND, "")
if err != nil {
fmt.Println(src, dest, err)
}
}
验证 macOS 上的可用常量:
在 macOS 上,可以检查 syscall 包中可用的常量:
package main
import (
"fmt"
"syscall"
)
func main() {
// 检查 macOS 上可用的挂载相关常量
fmt.Printf("MS_BIND: %v\n", syscall.MS_BIND)
}
关键点是:golang.org/x/sys/unix 包在不同操作系统上暴露的 API 不同,macOS 不支持 Linux 风格的 unix.Mount 函数,需要使用系统原生的 syscall.Mount。

