Golang中如何根据不同操作系统设置变量

Golang中如何根据不同操作系统设置变量 有什么关于如何为每个GOOS设置一组变量的提示吗? switch语句无法定义变量,无论是在main()函数中还是在init()块中。

	switch os := runtime.GOOS; os {
	case "windows", "arm64":
		var (
			foo = "bar1"
			// ... set more vars ...
		)
	case "arm":
		var (
			foo = "bar2"
			// ... set more vars ...
		)
	default:
		var (
			foo = "bar3"
			// ... set more vars ...
		)
	}

	fmt.Printf("%#v \n", foo) // 失败:"undefined: foo"

更多关于Golang中如何根据不同操作系统设置变量的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

作用域!明白了。所以,使用独立的变量声明,而不是在 switch/default 分支中声明,然后在 switch 中根据条件重置变量值,而不是重新声明。谢谢。

更多关于Golang中如何根据不同操作系统设置变量的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


嗯,如果将来要使用多个变量,使用 switch 语句并不那么符合惯用法,而且会变得复杂。更好的方法是使用条件编译,并为每个架构或操作系统创建单独的文件。可以参考 Dave Cheney 的文章了解如何实现这一点。

https://dave.cheney.net/2013/10/12/how-to-use-conditional-compilation-with-the-go-build-tool

试试这个:

package main

import (
	"fmt"
	"runtime"
)

func main() {
	var opsys string
	
	switch runtime.GOOS {
	    case "windows", "arm64":
		    opsys = "Microsoft Windows or ARM64"
	    case "arm":
		    opsys = "ARM"
	    case "linux":
		    opsys = "Linux"
	    default:
		    opsys = "other"
	}

	fmt.Printf("Host system: %#v \n", opsys)
}

在 Go Playground 上查看:Go Playground - The Go Programming Language

Go 是一门块作用域语言。

通过在 switch 语句内部声明 foo 变量,你只能在该代码块内部使用该 foo 变量。当执行离开该代码块时,如果存在另一个名为 foo 的变量,那么你的 fmt.Printf() 语句访问的将是那个变量。

这是一个更简单的示例:

package main
import "fmt"

func main() {
	var1 := 2
	{
		var1 := 3
		fmt.Printf("Inside the block, var1 = %d\n",var1)
	}
	fmt.Printf("Outside the block, var1 = %d\n",var1)
}

该程序输出:

在代码块内部,var1 = 3
在代码块外部,var1 = 2

在 Go Playground 上查看:Go Playground - The Go Programming Language

如果你不理解这一点,请移除第 6 行和第 9 行的 { } 大括号,然后再次运行代码。首先,你会收到关于重新声明 var1 的错误,因此将 var1 := 3 改为 var1 = 3

然后再次运行,查看输出结果:

在代码块内部,var1 = 3
在代码块外部,var1 = 3

在 Go Playground 上查看:Go Playground - The Go Programming Language

在Go语言中,switch语句的每个case分支都会创建一个独立的词法作用域,这就是为什么在switch外部无法访问case内部定义的变量。以下是几种正确的解决方案:

方案1:在switch外部声明变量,在case中赋值

package main

import (
	"fmt"
	"runtime"
)

func main() {
	var foo string
	
	switch os := runtime.GOOS; os {
	case "windows", "arm64":
		foo = "bar1"
	case "arm":
		foo = "bar2"
	default:
		foo = "bar3"
	}

	fmt.Printf("%#v \n", foo)
}

方案2:使用函数返回值

package main

import (
	"fmt"
	"runtime"
)

func getOSConfig() (foo string, bar int) {
	switch os := runtime.GOOS; os {
	case "windows", "arm64":
		foo = "bar1"
		bar = 100
	case "arm":
		foo = "bar2"
		bar = 200
	default:
		foo = "bar3"
		bar = 300
	}
	return
}

func main() {
	foo, bar := getOSConfig()
	fmt.Printf("foo: %#v, bar: %d\n", foo, bar)
}

方案3:使用结构体配置

package main

import (
	"fmt"
	"runtime"
)

type Config struct {
	Foo string
	Bar int
	Baz bool
}

func getConfig() Config {
	switch os := runtime.GOOS; os {
	case "windows", "arm64":
		return Config{
			Foo: "bar1",
			Bar: 100,
			Baz: true,
		}
	case "arm":
		return Config{
			Foo: "bar2",
			Bar: 200,
			Baz: false,
		}
	default:
		return Config{
			Foo: "bar3",
			Bar: 300,
			Baz: true,
		}
	}
}

func main() {
	config := getConfig()
	fmt.Printf("Config: %+v\n", config)
}

方案4:使用包级变量和init函数

package main

import (
	"fmt"
	"runtime"
)

var (
	foo string
	bar int
)

func init() {
	switch os := runtime.GOOS; os {
	case "windows", "arm64":
		foo = "bar1"
		bar = 100
	case "arm":
		foo = "bar2"
		bar = 200
	default:
		foo = "bar3"
		bar = 300
	}
}

func main() {
	fmt.Printf("foo: %#v, bar: %d\n", foo, bar)
}

方案5:使用map配置

package main

import (
	"fmt"
	"runtime"
)

var osConfig = map[string]struct {
	foo string
	bar int
}{
	"windows": {"bar1", 100},
	"arm64":   {"bar1", 100},
	"arm":     {"bar2", 200},
	"default": {"bar3", 300},
}

func main() {
	config, exists := osConfig[runtime.GOOS]
	if !exists {
		config = osConfig["default"]
	}
	
	fmt.Printf("foo: %#v, bar: %d\n", config.foo, config.bar)
}

推荐使用方案1或方案3,它们在代码可读性和维护性方面表现最好。方案1适合简单的变量赋值,方案3适合需要配置多个相关变量的场景。

回到顶部