私は、ブロックチェーン p2p ノードを起動する Go アプリに取り組んでいます。今のところ、ユーザーは手動で p2p ノードを開始し、ターミナル経由でデータを送信する必要があります。REST経由でブロックチェーンからデータを追加/読み取るためにHTTPサーバーを追加しようとしています。問題は、私が Cobra CLI を使用して p2p ノードの開始を処理しているため、別のコマンドを追加して go-gin HTTP サーバーを開始することです。最初の p2p ノードを開始すると、ブロックチェーンへの参照が返されます。その参照を http サーバーを開始する関数に渡すのに苦労しています。
構造体:
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,
}
}
p2p ノードを開始する Cobra コマンド
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
を最初のコマンドから 2 番目のコマンドに渡すことです。メソッド内Init()
なので返せないので、最初のコマンドのパッケージでグローバル変数を作成して、2番目のコマンドのパッケージからアクセスしてみましたが、いつもnil
で、理由がわかりません(おそらくスコープの問題)。
2 つのコマンドを 1 つのコマンドに混ぜて (p2p ノードと http サーバーを起動)、go ルーチンとチャネルを使用して を渡してみましnc
たが、go ルーチンはバックグラウンドで実行され、p2p ノードの起動にはユーザーの対話が必要なため、問題が発生しました。
これを達成するためのより良い/スムーズな方法はありますか?