在Windows开发机上编译Linux函数时遇到了问题。

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

Trouble compiling Linux functions on Windows Dev Machine

问题

我的应用程序在Linux服务器上运行,但我在Windows机器上进行开发。

我在编译来自"golang.org/x/sys/unix"包的函数和类型时遇到问题。以下是我代码的一部分无法编译的部分:

if runtime.GOOS == "linux" {
	var stat unix.Statfs_t
	err := unix.Statfs(mount, &stat)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		continue
	}

	totalSpace = uint64(stat.Blocks) * uint64(stat.Bsize)
	freeSpace = uint64(stat.Bfree) * uint64(stat.Bsize)
}

我使用JetBrains的Goland进行编译。我得到了这些错误:"undefined: unix.Statfs_t"和"undefined: unix.Statfs","编译完成,退出代码为2"。

我使用go get -u "golang.org/x/sys/unix"导入了该包,但仍然出现此错误。有人知道如何解决吗?

英文:

My app runs on a linux server, but I develop on a Windows machine.

I'm having problems compiling functions and types from the "golang.org/x/sys/unix" package. Here is a portion of my code not compiling well:

if runtime.GOOS == "linux" {
	var stat unix.Statfs_t
	err := unix.Statfs(mount, &stat)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		continue
	}

	totalSpace = uint64(stat.Blocks) * uint64(stat.Bsize)
	freeSpace = uint64(stat.Bfree) * uint64(stat.Bsize)
}

I'm compiling using Goland from JetBrains. I get these errors: "undefined: unix.Statfs_t" and "undefined: unix.Statfs", "Compilation finished with exit code 2".

I imported the package with go get -u "golang.org/x/sys/unix", but I still get this error. Anyone know how to fix this?

答案1

得分: 3

Go源文件包的导入由编译器处理。运行时检查runtime.GOOS == "linux"不起作用,因为太晚了。可以使用Go编译器的构建约束

对于Linux和Windows,可以同时使用显式和文件名隐式的构建约束。

disk/disk.go:

package main

import (
	"fmt"
	"os"
	"path/filepath"
)

func main() {
	mount := string(filepath.Separator)
	total, free, err := DiskSpace(mount)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	fmt.Println(total, free)
}

disk/disk_linux.go:

package main

import (
	"golang.org/x/sys/unix"
)

func DiskSpace(mount string) (total, free uint64, err error) {
	var stat unix.Statfs_t
	err = unix.Statfs(mount, &stat)
	if err != nil {
		return 0, 0, err
	}
	total = uint64(stat.Blocks) * uint64(stat.Bsize)
	free = uint64(stat.Bfree) * uint64(stat.Bsize)
	return total, free, nil
}

disk/disk_windows.go:

package main

import (
	"golang.org/x/sys/windows"
)

func DiskSpace(dir string) (total, free uint64, err error) {
	var (
		directoryName              = windows.StringToUTF16Ptr(dir)
		freeBytesAvailableToCaller uint64
		totalNumberOfBytes         uint64
		totalNumberOfFreeBytes     uint64
	)
	err = windows.GetDiskFreeSpaceEx(
		directoryName,
		&freeBytesAvailableToCaller,
		&totalNumberOfBytes,
		&totalNumberOfFreeBytes,
	)
	if err != nil {
		return 0, 0, err
	}
	return totalNumberOfBytes, totalNumberOfFreeBytes, nil
}

disk/disk_other.go:

//go:build !(linux || windows)

package main

import (
	"fmt"
)

func DiskSpace(mount string) (total, free uint64, err error) {
	err = fmt.Errorf("DiskSpace not implemented for this OS")
	return 0, 0, err
}

在Linux上:

disk$ go build && ./disk
64183046144 37856325632
$ 

在Windows上:

disk>go build && disk.exe
205507317760 59385081856
>

你可能想考虑在开发中使用WSL。

Windows Subsystem for Linux (WSL)允许开发人员在Windows上直接运行GNU/Linux环境,无需传统虚拟机或双启动设置的开销。

英文:

Go source file package imports are processed by the compiler. A runtime check, runtime.GOOS == "linux", is not going to work; it's too late. Use Go compiler build constraints.


For both Linux and Windows, using both explicit and file name implicit build constraints,

disk/disk.go:

package main

import (
    "fmt"
    "os"
    "path/filepath"
)

func main() {
    mount := string(filepath.Separator)
    total, free, err := DiskSpace(mount)
    if err != nil {
	    fmt.Fprintln(os.Stderr, err)
	    os.Exit(1)
    }
    fmt.Println(total, free)
}

disk/disk_linux.go:

package main

import (
    "golang.org/x/sys/unix"
)

func DiskSpace(mount string) (total, free uint64, err error) {
    var stat unix.Statfs_t
    err = unix.Statfs(mount, &stat)
    if err != nil {
	    return 0, 0, err
    }
    total = uint64(stat.Blocks) * uint64(stat.Bsize)
    free = uint64(stat.Bfree) * uint64(stat.Bsize)
    return total, free, nil
}

disk/disk_windows.go:

package main

import (
	"golang.org/x/sys/windows"
)

func DiskSpace(dir string) (total, free uint64, err error) {
	var (
		directoryName              = windows.StringToUTF16Ptr(dir)
		freeBytesAvailableToCaller uint64
		totalNumberOfBytes         uint64
		totalNumberOfFreeBytes     uint64
	)
	err = windows.GetDiskFreeSpaceEx(
		directoryName,
		&freeBytesAvailableToCaller,
		&totalNumberOfBytes,
		&totalNumberOfFreeBytes,
	)
	if err != nil {
		return 0, 0, err
	}
	return totalNumberOfBytes, totalNumberOfFreeBytes, nil
}

disk/disk_other.go:

//go:build !(linux || windows)

package main

import (
    "fmt"
)

func DiskSpace(mount string) (total, free uint64, err error) {
    err = fmt.Errorf("DiskSpace not implemented for this OS")
    return 0, 0, err
}

On Linux:

disk$ go build && ./disk
64183046144 37856325632
$ 

On Windows:

disk>go build && disk.exe
205507317760 59385081856
>

You may want to consider using WSL for development.

> Windows Subsystem for Linux (WSL) lets developers run a GNU/Linux environment directly on Windows, unmodified, without the overhead of a traditional virtual machine or dual-boot setup.


huangapple
  • 本文由 发表于 2023年3月19日 09:40:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/75779645.html
匿名

发表评论

匿名网友

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

确定