CLI 命令行接口

直到现在,我们的实现还没有提供任何操作接口给外界使用。我们先前的例子中在 main 函数中执行新建区块链 NewBlockchain,还有新增区块 bc.AddBlock 的方法。现在可以改善,增加命令行操作接口了。我们需要如下这样的命令:

$ blockchain_go addblock “Pay 0.031337 for a coffee”

$ blockchain_go printchain

所有的命令行关联的操作会被 CLI 结构处理:

type CLI struct {
        bc *Blockchain
}

在 Run中加入CLI的接入点:

func (cli *CLI) Run() {
        cli.validateArgs()
addBlockCmd := flag.NewFlagSet("addblock", flag.ExitOnError)
        printChainCmd := flag.NewFlagSet("printchain", flag.ExitOnError)
addBlockData := addBlockCmd.String("data", "", "Block data")
switch os.Args[1] {
        case "addblock":
                err := addBlockCmd.Parse(os.Args[2:])
        case "printchain":
                err := printChainCmd.Parse(os.Args[2:])
        default:
                cli.printUsage()
                os.Exit(1)
        }
if addBlockCmd.Parsed() {
                if *addBlockData == "" {
                        addBlockCmd.Usage()
                        os.Exit(1)
                }
                cli.addBlock(*addBlockData)
        }
if printChainCmd.Parsed() {
                cli.printChain()
        }
}

使用标准的 flag 解析这些参数

addBlockCmd := flag.NewFlagSet("addblock", flag.ExitOnError)
printChainCmd := flag.NewFlagSet("printchain", flag.ExitOnError)
addBlockData := addBlockCmd.String("data", "", "Block data")

首先,创建两个子命令, addblock 和 printfchain,用 -add 标记作为 addblock 的参数数据标识。printfchain 不用参数:

switch os.Args[1] {
case "addblock":
        err := addBlockCmd.Parse(os.Args[2:])
case "printchain":
        err := printChainCmd.Parse(os.Args[2:])
default:
        cli.printUsage()
        os.Exit(1)
}

检测用户输入的参数和解析相关的 flag 子命令。

if addBlockCmd.Parsed() {
        if *addBlockData == "" {
                addBlockCmd.Usage()
                os.Exit(1)
        }
        cli.addBlock(*addBlockData)
}
if printChainCmd.Parsed() {
        cli.printChain()
}

解析出的子命令该执行的相关函数:

func (cli *CLI) addBlock(data string) {
        cli.bc.AddBlock(data)
        fmt.Println("Success!")
}
func (cli *CLI) printChain() {
        bci := cli.bc.Iterator()
for {
                block := bci.Next()
fmt.Printf("Prev. hash: %x\n", block.PrevBlockHash)
                fmt.Printf("Data: %s\n", block.Data)
                fmt.Printf("Hash: %x\n", block.Hash)
                pow := NewProofOfWork(block)
                fmt.Printf("PoW: %s\n", strconv.FormatBool(pow.Validate()))
                fmt.Println()
if len(block.PrevBlockHash) == 0 {
                        break
                }
        }
}

现在的代码很像我们之些写的那些。比较不同的是现在使用的是 BlockchainIterator去遍历整个区块链中的区块。 
最后修改 main 函数:

func main() {
        bc := NewBlockchain()
        defer bc.db.Close()
cli := CLI{bc}
        cli.Run()
}

注意,第一次执行时,如果BoltDB中没有区块链,则无论输入什么参数,都会创建一个区块链。 
现在可以检测一下我们的代码是否工作OK了: 
先安装BoltDB

$ go get github.com/boltdb/bolt/…

执行程序:

$ blockchain_go printchain

No existing blockchain found. Creating a new one… 
Mining the block containing “Genesis Block” 
000000edc4a82659cebf087adee1ea353bd57fcd59927662cd5ff1c4f618109b 
Prev. hash: 
Data: Genesis Block 
Hash: 000000edc4a82659cebf087adee1ea353bd57fcd59927662cd5ff1c4f618109b 
PoW: true

$ blockchain_go addblock -data “Send 1 BTC to Ivan”

Mining the block containing “Send 1 BTC to Ivan” 
000000d7b0c76e1001cdc1fc866b95a481d23f3027d86901eaeb77ae6d002b13 
Success!

$ blockchain_go addblock -data “Pay 0.31337 BTC for a coffee”

Mining the block containing “Pay 0.31337 BTC for a coffee” 
000000aa0748da7367dec6b9de5027f4fae0963df89ff39d8f20fd7299307148 
Success!

$ blockchain_go printchain

Prev. hash: 000000d7b0c76e1001cdc1fc866b95a481d23f3027d86901eaeb77ae6d002b13 
Data: Pay 0.31337 BTC for a coffee 
Hash: 000000aa0748da7367dec6b9de5027f4fae0963df89ff39d8f20fd7299307148 
PoW: true 
Prev. hash: 000000edc4a82659cebf087adee1ea353bd57fcd59927662cd5ff1c4f618109b 
Data: Send 1 BTC to Ivan 
Hash: 000000d7b0c76e1001cdc1fc866b95a481d23f3027d86901eaeb77ae6d002b13 
PoW: true 
Prev. hash: 
Data: Genesis Block 
Hash: 000000edc4a82659cebf087adee1ea353bd57fcd59927662cd5ff1c4f618109b 
PoW: true 
本章总结 
本章我们实现了区块的持久化,还有完善了遍历信息来支持按序打印所有的区块。下一章我们将会实现 address,wallet,transaction。敬请期待!

 

2.4 接口

相关文章:

  • 2021-09-06
  • 2021-07-22
  • 2021-11-16
  • 2021-09-18
  • 2022-12-23
  • 2021-07-04
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-09-27
  • 2022-02-22
  • 2021-12-05
  • 2021-11-27
  • 2021-07-09
相关资源
相似解决方案