我正在开发一个启动区块链 p2p 节点的 Go 应用程序。目前,用户必须手动启动 p2p 节点并通过终端提交数据。我正在尝试添加一个 HTTP 服务器以通过 REST 从区块链添加/读取数据。问题是我正在使用 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
从第一个命令传递到第二个命令。它无法返回,因为它在Init()
方法内部,所以我尝试在第一个命令的包中创建一个全局变量,然后从第二个命令包中访问它,但总是nil
如此,我不明白为什么(可能是范围问题)。
我尝试将这两个命令混合为一个(启动 p2p 节点和 http 服务器),使用 go 例程和通道来传递nc
,但这会导致问题,因为 go 例程在后台运行,并且启动 p2p 节点需要用户交互。
有没有更好/更顺畅的方法来实现这一目标?