在运行时为不同操作系统选择函数的正确方法是什么?

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

Proper way to choose func at runtime for different operating systems

问题

我真的很喜欢使用GO进行交叉编译和跨平台操作。我有一个关于操作系统的问题,我想知道如何根据操作系统执行/编译函数,类似于#ifdef / #else的构造。

假设我有一个函数,它将信息插入操作系统的控制结构,以便在用户下次启动系统时启动进程。在Windows上,我会更新用户的"RUN/RUNONCE"注册表项;在Mac上,会有一个plist条目,等等。

实际上,我想能够编写类似于以下代码的函数(或者有重载的特定于操作系统的函数):

func setStartupProcessLaunch () {
    if [操作系统是Windows] {
        updateRegistry(){}
    } else if [操作系统是Darwin] {
        updatePlist(){}
    } else if [操作系统是Linux] {
        doLinuxthing() {}
    }
}

由于静态编译,任何未被调用的函数都会被标记为编译错误。所以理想情况下,我希望能够在#ifdef WINDOWS、#ifdef MAC等块中包围我的"doSpecificOS()"函数。有什么正确的方法可以实现这一点吗?我希望不需要为每个操作系统平台创建多个项目树。

英文:

I really like the cross-compile/platform ease for many tasks that I can get with GO. I have a question regarding, I guess, the equivalent of a #ifdef / #else type of construct for executing/compiling a function based upon the operating system.

Here's the scenario - let's say I have a function that inserts information into the OS's control structures to launch a process at the next time the user starts up their system. On Windows I would update the 'RUN/RUNONCE' registry entry for the user, on MAC there would be a plist entry, etc.

In essence, I'd like to be able to write someone analogous to this (or have overloaded OS specific functions):

func setStartupProcessLaunch () {
    if [OS is Windows] {
        updateRegistry(){}
    } else if [OS is Darwin] {
        updatePlist(){}
    } else if [OS is Linux] {
        doLinuxthing() {}
    }
}

Given the static compilation, any of the routines that aren't called would be flagged as a compilation error. So ideally, I'd like to surround my 'doSpecificOS()' functions in #ifdef WINDOWS, #ifdef MAC type of blocks -- what's the proper way to accomplish this? My hope is that I don't need to create several project trees of the same program for each OS platform.

答案1

得分: 22

你可以按照以下模式创建文件:<pkgname>_<osname>.go

例如:

  • your_package_linux.go
  • your_package_darwin.go
  • your_package_windows.go

每个文件可以包含具体操作系统的函数定义,在你的情况下是 func setStartupProcessLaunch()

你可以在标准的 os/signal 包中查看它是如何实现的,例如

英文:

You could create files with following pattern: &lt;pkgname&gt;_&lt;osname&gt;.go

For example:

  • your_package_linux.go
  • your_package_darwin.go
  • your_package_windows.go

Each file could contain function definition for concrete os, in your case it is func setStartupProcessLaunch().

You could see how it is implemented in standard os/signal package for example.

答案2

得分: 10

你可以在这里阅读有关**构建约束(Build Constraints)的信息:http://golang.org/pkg/go/build/(你可以创建三个文件,每个文件都包含特定操作系统的逻辑)。
或者你可以检查
runtime.GOOS**获取操作系统名称字符串。

英文:

You can read about Build Constraints here http://golang.org/pkg/go/build/ (you can make three files, each file has the logic for a specific OS)
Or maybe you can check the runtime.GOOS for the OS name string

答案3

得分: -3

你可以将函数放在一个数组或映射中,如果它们都接受相同数量/类型的参数并具有相同的返回类型。

这里有一个示例来说明:

package main

import (
    "fmt"
)

var functionMap = map[string]func(int) int{}
var functionArray = [2]func(int) int{nil, nil}

func windowsFunc(x int) int {
    fmt.Printf("Hi from windowsFunc(%d)\n", x)
    return 0
}

func linuxFunc(x int) int {
    fmt.Printf("Hi from linuxFunc(%d)\n", x)
    return 1
}

func main() {
    functionMap["Windows"] = windowsFunc
    functionMap["Linux"] = linuxFunc

    functionArray[0] = windowsFunc
    functionArray[1] = linuxFunc

    fmt.Printf("Calling functionMap[\"Windows\"]: ")
    functionMap["Windows"](123)

    fmt.Printf("Calling functionArray[1]: ")
    functionArray[1](456)
}

输出结果为:

Calling functionMap["Windows"]: Hi from windowsFunc(123)
Calling functionArray1: Hi from linuxFunc(456)

英文:

You could put your functions in an array or map if they all the take the same number/kinds of arguments and have the same return type.

Here's an example to illustrate:

package main

import (
&quot;fmt&quot;
)

var functionMap = map[string]func(int)int{}
var functionArray = [2]func(int)int{nil, nil}

func windowsFunc(x int) int {
    fmt.Printf(&quot;Hi from windowsFunc(%d)\n&quot;, x)
    return 0 
}

func linuxFunc(x int) int {
    fmt.Printf(&quot;Hi from linuxFunc(%d)\n&quot;, x)
    return 1
}


func main() {
    functionMap[&quot;Windows&quot;] = windowsFunc
    functionMap[&quot;Linux&quot;] = linuxFunc

    functionArray[0] = windowsFunc
    functionArray[1] = linuxFunc

    fmt.Printf(&quot;Calling functionMap[\&quot;Windows\&quot;]: &quot;)
    functionMap[&quot;Windows&quot;](123)

    fmt.Printf(&quot;Calling functionArray[1]: &quot;)
    functionArray[1](456)
}

And the output is:

>Calling functionMap["Windows"]: Hi from windowsFunc(123)<br>
Calling functionArray1: Hi from linuxFunc(456)

huangapple
  • 本文由 发表于 2013年12月6日 21:04:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/20424623.html
匿名

发表评论

匿名网友

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

确定