Передача переменной из команды кобра в другую - PullRequest
0 голосов
/ 18 марта 2020

Я работаю над приложением Go, которое запускает p2p-узлы блокчейна. На данный момент пользователь должен вручную запустить узлы p2p и отправить данные через терминал. Я пытаюсь добавить HTTP-сервер для добавления / чтения данных из блокчейна через REST. Проблема в том, что я обрабатываю запуск узлов p2p с помощью Cobra CLI, поэтому, когда я добавил еще одну команду для запуска go -gin HTTP-сервера. Запуск первого узла p2p возвращает ссылку на блокчейн, и я изо всех сил пытаюсь передать эту ссылку функции, которая запускает http-сервер.

structs:

type P2pConfig struct {
    ListenF int
    Target string
    Secio bool
    Seed int64
}

type HttpConfig struct {
    HttpPort string
}

type Block struct {
    Index     int
    Timestamp string
    BPM       string
    Hash      string
    PrevHash  string
}

type Chain struct {
    BlockChain []Block
    P2pConfig *P2pConfig
    HttpConfig *HttpConfig
}

func NewBlockChain(c *P2pConfig, h *HttpConfig) *Chain {
    return &Chain {
        P2pConfig:c,
        HttpConfig:h,
    }
}

Команда Cobra запустить узел p2p

func init() {
    CommandServe = &cobra.Command{
        Use:   "bc",
        Short: "Start the BlockChain",
        Long:  ``,
        Run: func(CommandServe *cobra.Command, args []string) {

            if _, err := serve(); err != nil {
                fmt.Fprintln(os.Stderr, err)
            }
        },
    }

    CommandServe.Flags().IntVar(&p2pPort, "l", 8199, "port: wait for incoming connections")
    CommandServe.Flags().StringVar(&target, "d", "", "target peer to dial")
    CommandServe.Flags().BoolVar(&secio, "secio", true, "enable secio")
    CommandServe.Flags().Int64Var(&seed, "seed", 0, "set random seed for id generation")
    CommandServe.Flags().StringVar(&httpPort, "p", ":8090", "port of the http ledger")

}

func serve() (*core.Chain, error) {

    c := core.NewBlockChain(&core.P2pConfig{
        ListenF: p2pPort,
        Target:  target,
        Secio:   secio,
        Seed:    seed,
    }, &core.HttpConfig{
        HttpPort: httpPort})

    log.Println("running p2p server")

    nc, err := core.Launch(c)
    if err != nil {
        return nil, err
    }

    return nc, nil

}

Запуск HTTP-сервера

func init() {
    CommandServe = &cobra.Command{
        Use:   "hs",
        Short: "Start the http server",
        Long:  ``,
        Run: func(CommandServe *cobra.Command, args []string) {
            if err := serve(); err != nil {
                fmt.Fprintln(os.Stderr, err)
            }
        },
    }
}

func serve() error {

    log.Println("running http server")
    go func() error {
        err := nc.Run(":8090") //causing error here because nc is not recognizable yet
        if err != nil {
            return err
        }
        return nil
    }()

    return nil
}

Проблема заключается в передаче переменной nc из первой команды во вторую команду. Его нельзя вернуть, потому что он внутри метода Init(), поэтому я попытался создать глобальную переменную в пакете команды fist, а затем получить к ней доступ из пакета второй команды, но это всегда nil, и я не понимаю, почему (возможно, проблема области видимости).

Я попытался объединить две команды в одну (запустить узлы p2p и http-сервер), использовать go подпрограммы и каналы для передачи nc, но это вызвало проблему, поскольку go подпрограммы выполняются в фоновом режиме, а запуск узлов p2p требует интерактивности пользователя.

Есть ли лучший / более плавный способ добиться этого?

...