Как сделать метапрограммирование или условную компиляцию на функциональном уровне вместо платформы в GoLang? - PullRequest
0 голосов
/ 13 сентября 2018

Я пытаюсь создать двоичный файл, который будет содержать разные модули, но в то же время я хочу, чтобы пользователь мог выбирать, какие модули будут включены в сгенерированный двоичный файл.

Я также спросил в SE stackoverflow: https://softwareengineering.stackexchange.com/questions/378319/building-object-with-arbitrary-functionalities

Я думаю, что это не в моих знаниях, и мне может понадобиться помощь с этим.

Я подумываю написать еще одну программу Go, которая удаляет функции из файлов go перед компиляцией. Я никогда не делал / не слышал об этом раньше, и это кажется немного хакерским. Просто интересно, что будет лучшим подходом к этой проблеме.

Спасибо! Я также приложил код тестирования, который я использовал.

package main

import (
"strings"
"fmt"
"bufio"
"os"
"reflect"
"./f"
"./g"
)



func main() {
    // assume this is user input, enable f and disable g
    var options = map[string]bool{
        "f":true,
        "g":false,
    }

    // a map for all the functions
    m := map[string]interface{}{
        "f": f.F,
        "g": g.G,
    }
    // remove disabled function from the map
    for k,v := range options {
        if v == false{
            delete(m, k)
        }
    }


    // and now if user wanna use function g, it will return not ok since it is disabled in setting
    // and function f will work
    fmt.Println("Enter Options(f/g)")
    reader := bufio.NewReader(os.Stdin)
    user_input, _ := reader.ReadString('\n')
    user_input = strings.TrimSuffix(user_input, "\n")
    fmt.Println(user_input)
    // take input from user... f
    if x,ok := m[user_input]; ok {
        function := reflect.ValueOf(x)
        function_input := make([]reflect.Value, 1)
        function_input[0]=reflect.ValueOf("123")
        function.Call(function_input)
        fmt.Println("OK")
   } else {
        fmt.Println("Option doesnt exist or disabled.")
   }
}

Упаковка г

package g

import "fmt"

func G(p string) { // removed second arguemt
    fmt.Println("function g parameters:", p)
}

Пакет Ф

package f

import "fmt"

func F(p string) {
    fmt.Println("function f parameter:", p)
}

Я просто запустил env GOOS=linux GOARCH=386 go build test.go и objdump -t test, чтобы посмотреть, включена ли функция в двоичный файл после переключения значений параметров.

И вы можете видеть, что f и g включены в двоичный файл, независимо от того, является ли значение параметра истинным или ложным.

080bef10 g     F .text       000000a7 main.f
080befc0 g     F .text       000000c0 main.g
080bf080 g     F .text       00000544 main.main
080bf5d0 g     F .text       00000052 main.init

1 Ответ

0 голосов
/ 13 сентября 2018

Вы можете использовать Построить ограничения Вам необходимо поместить каждый из ваших модулей в отдельный файл (ы).Они не должны быть в отдельном пакете.

Вверху каждого файла в модуле foo вы размещаете:

// +build foo

И в верхней части каждого файла вbar пакет, который вы поместите

// +build bar

Теперь вы можете собрать свой бинарный файл с помощью модуля foo,

go build -tags foo ...

или обоих

go build -tags 'foo bar' ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...