区块链V3版本实现之五
迭代器分析:
作用:遍历容器,将数据逐个返回,防止一次性加载到内存,所以一点一点读取。
类比于for循环里面的range
区块链迭代器图示如下,最初指向最后一个区块,返回区块,指针前移,直至第一个区块。
部分代码(blockchain.go文件中定义和创建迭代器):
1 //定义一个区块链的迭代器,包含db,current 2 type BlockChainIterator struct { 3 db *bolt.DB 4 current []byte //当前所指向区块的哈希值 5 } 6 7 //创建迭代器,使用bc进行初始化 8 func (bc *BlockChain) NewIterator() *BlockChainIterator { 9 return &BlockChainIterator{bc.db,bc.tail} 10 }
部分代码(blockchain.go文件中迭代器Next函数实现):
1 func (it *BlockChainIterator) Next() *Block { 2 3 var block Block 4 5 it.db.View(func(tx *bolt.Tx) error { 6 b := tx.Bucket([]byte(blockBucketName)) 7 if b == nil{ 8 fmt.Printf("bucket不存在,请检查!\n") 9 os.Exit(1) 10 } 11 12 //真正读取数据 13 blockInfo /*block的字节流*/ := b.Get(it.current) 14 block = *Deserialize(blockInfo) 15 16 it.current = block.PrevBlockHash 17 return nil 18 }) 19 20 return &block 21 }
部分代码(main.go文件中的代码改进):
1 package main 2 3 import ( 4 "bytes" 5 "fmt" 6 "time" 7 ) 8 9 func main() { 10 fmt.Printf("HelloWorld!!!\n") 11 12 bc := NewBlockChain() 13 defer bc.db.Close() 14 15 bc.AddBlock("hello") 16 bc.AddBlock("hello1") 17 bc.AddBlock("hello2") 18 bc.AddBlock("hello3") 19 20 it := bc.NewIterator() 21 22 //区块打印输出 23 for { 24 block := it.Next() 25 fmt.Printf("Version : %d\n", block.Version) 26 fmt.Printf("PrevBlockHash : %x\n", block.PrevBlockHash) 27 fmt.Printf("MerKleRoot : %x\n", block.MerKleRoot) 28 29 timeFormat := time.Unix(int64(block.TimeStamp), 0).Format("2006-01-02 15:04:05") 30 fmt.Printf("TimeStamp : %s\n", timeFormat) 31 32 fmt.Printf("Difficulity : %d\n", block.Difficulity) 33 fmt.Printf("Nonce : %d\n", block.Nonce) 34 fmt.Printf("Hash : %x\n", block.Hash) 35 fmt.Printf("Data : %s\n", block.Data) 36 37 pow := NewProofOfWork(block) 38 fmt.Printf("IsValid : %v\n", pow.IsValid()) 39 40 //判断边界 41 if bytes.Equal(block.PrevBlockHash,[]byte{}){ 42 fmt.Printf("区块链遍历结束!\n") 43 break 44 } 45 } 46 }
显示效果: