Правильный способ выбора func во время выполнения для разных операционных систем

Мне действительно нравится легкость кросс-компиляции/платформы для многих задач, которые я могу получить с помощью GO. У меня есть вопрос относительно, я думаю, эквивалента конструкции типа #ifdef/#else для выполнения/компиляции функции, основанной на операционной системе.

Вот сценарий - скажем, у меня есть функция, которая вставляет информацию в структуры управления ОС для запуска процесса при следующем запуске системы пользователем. В Windows я бы обновил запись реестра "RUN/RUNONCE" для пользователя, в MAC была бы запись plist и т.д.

По сути, я хотел бы иметь возможность написать кого-то, аналогичного этому (или перегрузить определенные функции ОС):

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

При статической компиляции любая из не вызванных подпрограмм будет помечена как ошибка компиляции. Поэтому в идеале я хотел бы заключить мои функции doSpecificOS() в блоки #ifdef WINDOWS, #ifdef MAC-типа - как правильно это сделать? Я надеюсь, что мне не нужно создавать несколько деревьев проектов одной и той же программы для каждой платформы ОС.

Ответ 1

Вы можете создавать файлы со следующим шаблоном: <pkgname>_<osname>.go

Например:

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

Каждый файл может содержать определение функции для конкретных os, в вашем случае это func setStartupProcessLaunch().

Вы можете увидеть, как он реализован в стандартном os/signal пакете .

Ответ 2

Здесь вы можете прочитать Конструктивные ограничения http://golang.org/pkg/go/build/ (вы можете сделать три файла, каждый файл имеет логика для конкретной ОС)
Или, может быть, вы можете проверить runtime.GOOS для строки имени операционной системы

Ответ 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)
}

И результат:

Вызов функцииMap [ "Windows" ]: Привет от windowsFunc (123)
Вызов функцииArray [1]: Привет от linuxFunc (456)