丁丁打折网 - 网友优惠券分享网站,有688999个用户

京东优惠券 小米有品优惠券

当前位置 : 首页>web3>Go实战:30分钟自制区块链【教程】

Go实战:30分钟自制区块链【教程】

类别:web3 发布时间:2025-10-24 08:25

区块链:不仅仅是加密货币

自互联网诞生以来,区块链技术就被誉为最具颠覆性的创新之一。尽管很多人将区块链与那些价格波动剧烈的数字资产划等号,但实际上,区块链的应用远不止于此。加密货币只是区块链技术的一小部分,许多实际应用正由各个机构悄悄地推动着。

随着区块链技术的快速发展,越来越多的人开始意识到,掌握区块链的基础知识及其技术影响力至关重要。

构建自己的区块链听起来似乎遥不可及,但实际上并没有那么复杂。本文将带你使用 Go 语言(2021 年最受欢迎的编程语言之一)来实现一个简单的区块链。准备好了吗?让我们开始吧!

区块链原理

区块链,顾名思义,就是一个由信息块(Block)组成的链条。这些信息块通过哈希值(Hash)相互连接。哈希值是由输入数据生成的加密的、固定长度的输出。由于每个区块都通过哈希值引用前一个区块,因此,如果想要篡改链上的任何一个区块,就必须同时修改链上所有后续区块的哈希值。

区块链中的每个区块都可以包含几乎任何类型的数据。一个基本的框架会包含每个区块过去交易的所有记录。比特币就是以类似的方式运作的,因此你可以追溯每一笔交易,直到中本聪的首次加密货币交易。

假设我们要创建一个包含三个区块的区块链。第一个区块是创世区块,由于它是第一个区块,所以“前一个哈希值”字段为空。我们仍然使用时间戳和初始交易作为哈希算法的输入,该算法会生成一串数字和字母,这就是创世区块的哈希值。

对于第二个区块,我们将创世区块的哈希值作为第二个区块的“前一个哈希值”。这个操作将创世区块和第二个区块连接起来!接下来,我们将时间戳、交易列表和前一个哈希值作为哈希算法的输入,该算法会为我们提供一个表示第二个区块的新哈希值。

我们可以根据需要重复这个过程任意多次,除了区块的有效性和存储区块链的能力之外(比特币的区块链大约为 330 GB),没有任何其他限制。

用 Go 语言构建一个简单的区块链

构建区块链的第一步是定义什么是区块。Go 语言可以轻松地创建自定义类型。我们可以使用以下代码来定义 Block 类型。在这里,Block 结构体有四个字段,与上图中的区块结构相对应。

type Block struct { timestamp time.Time transactions []string prevHash []byte Hash []byte}

下一步是创建一个构造函数(Go 版本),用于创建新的区块。该函数的输入是一个字符串数组(表示交易)和一个字节数组(表示前一个区块的哈希值)。接下来,我们将研究 NewHash() 函数,这是我们下一步要实现的功能。

func NewBlock(transactions []string, prevHash []byte) *Block { currentTime := time.Now() return &Block{ timestamp: currentTime, transactions: transactions, prevHash: prevHash, Hash: NewHash(currentTime, transactions, prevHash), }}

NewHash() 函数将时间、交易列表和前一个哈希值作为输入参数,并返回一个字节数组,表示新生成的哈希值。在这个函数中,我们基本上只是将所有输入都混合到一个名为 input 的字节数组中。我们使用 append() 函数来附加 time 参数和 prevHash。通过将 time 转换为 string,并使用 ...prevHash 切片作为后缀附加到 time 切片。

然后,我们遍历 transactions,并将每个单独的 transaction 附加到 input 数据块。有趣的语法 string(rune(transaction))... 只是 Go 语言中将 transactions 中的每个元素转换为可以附加到的切片的一种方法。

func NewHash(time time.Time, transactions []string, prevHash []byte) []byte { input := append(prevHash, time.String()...) for transaction := range transactions { input = append(input, string(rune(transaction))...) } hash := sha256.Sum256(input) return hash[:]}

最后,我们使用 crypto 包调用 sha256.Sum256() 函数,并将 input 作为参数。这将为我们的所有数据输入提供一个新的哈希表示。我们返回时使用 hash[:][:] 语法将在返回时将 hash 切成适当的长度。

这实际上是我们开始链接区块链所需的全部内容。当然,我们希望在程序中看到某种输出,因此可以添加一些辅助方法,以便在打印时使用:

func printBlockInformation(block *Block) { fmt.Printf("\ttime: %s\n", block.timestamp.String()) fmt.Printf("\tprevHash: %x\n", block.prevHash) fmt.Printf("\tHash: %x\n", block.Hash) printTransactions(block)}

func printTransactions(block *Block) {fmt.Println("\tTransactions:")for i, transaction := range block.transactions {fmt.Printf("\t\t%v: %q\n", i, transaction)}}

现在剩下的就是创建新的交易、区块和哈希值。我们可以通过 main 方法来实现这一点。我们定义了一个字符串数组来记录区块链中的交易。另请注意,我们如何传递一个空字节数组给 NewBlock() 来生成第一个区块,称为 genesisBlock

func main() {genesisTransactions := []string{"Izzy sent Will 50 bitcoin", "Will sent Izzy 30 bitcoin"}genesisBlock := NewBlock(genesisTransactions, []byte{})fmt.Println("--- First Block ---")printBlockInformation(genesisBlock)

block2Transactions := []string{"John sent Izzy 30 bitcoin"}block2 := NewBlock(block2Transactions, genesisBlock.Hash)fmt.Println("--- Second Block ---")printBlockInformation(block2)block3Transactions := []string{"Will sent Izzy 45 bitcoin", "Izzy sent Will 10 bitcoin"}block3 := NewBlock(block3Transactions, block2.Hash)fmt.Println("--- Third Block ---")printBlockInformation(block3)

}

为了创建新的区块,我们将前一个区块的哈希值传递给 NewBlock() 函数,以及对应的交易历史记录。如果你想在一个地方查看整个程序,代码如下:

package main

import ("crypto/sha256""fmt""time")

type Block struct {timestamp time.Timetransactions []stringprevHash []byteHash []byte}

func main() {genesisTransactions := []string{"Izzy sent Will 50 bitcoin", "Will sent Izzy 30 bitcoin"}genesisBlock := NewBlock(genesisTransactions, []byte{})fmt.Println("--- First Block ---")printBlockInformation(genesisBlock)

block2Transactions := []string{"John sent Izzy 30 bitcoin"}block2 := NewBlock(block2Transactions, genesisBlock.Hash)fmt.Println("--- Second Block ---")printBlockInformation(block2)block3Transactions := []string{"Will sent Izzy 45 bitcoin", "Izzy sent Will 10 bitcoin"}block3 := NewBlock(block3Transactions, block2.Hash)fmt.Println("--- Third Block ---")printBlockInformation(block3)

}

func NewBlock(transactions []string, prevHash []byte) *Block {currentTime := time.Now()return &Block{timestamp: currentTime,transactions: transactions,prevHash: prevHash,Hash: NewHash(currentTime, transactions, prevHash),}}

func NewHash(time time.Time, transactions []string, prevHash []byte) []byte {input := append(prevHash, time.String()...)for transaction := range transactions {input = append(input, string(rune(transaction))...)}hash := sha256.Sum256(input)return hash[:]}

func printBlockInformation(block *Block) {fmt.Printf("\ttime: %s\n", block.timestamp.String())fmt.Printf("\tprevHash: %x\n", block.prevHash)fmt.Printf("\tHash: %x\n", block.Hash)printTransactions(block)}

func printTransactions(block *Block) {fmt.Println("\tTransactions:")for i, transaction := range block.transactions {fmt.Printf("\t\t%v: %q\n", i, transaction)}}

如果要运行此程序,将得到以下输出:

$ go run example.go--- First Block ---time: 2021-04-05 15:12:18.813294 -0600 MDT m=+0.000074939prevHash:Hash: 43ec51c50d2b9565f221155a29d8b72307247b08eaf6731ccaTransactions:0: "Izzy sent Will 50 bitcoin"1: "Will sent Izzy 30 bitcoin"--- Second Block ---time: 2021-04-05 15:12:18.813477 -0600 MDT m=+0.000257244prevHash: 43ec51c50d2b9565f221155a29d8b72307247b08eaf6731ccaHash: fcce5323a35cb67b45fe75866582db00fd32baeb92aac448c7Transactions:0: "John sent Izzy 30 bitcoin"--- Third Block ---time: 2021-04-05 15:12:18.813488 -0600 MDT m=+0.000269168prevHash: fcce5323a35cb67b45fe75866582db00fd32baeb92aac448c7Hash: fc1d3eee286970d85812b47c3a5bf016ae8c1de4f86b8ace972ffaTransactions:0: "Will sent Izzy 45 bitcoin"1: "Izzy sent Will 10 bitcoin"

这个过程可能看起来有些粗糙,但这正是创建自己的区块链的基础!

丁丁打折网©版权所有,未经许可严禁复制或镜像 ICP证: 湘ICP备20009233号-2

Powered by 丁丁打折网本站为非营利性网站,本站内容均来自网络转载或网友提供,如有侵权或夸大不实请及时联系我们删除!本站不承担任何争议和法律责任!
技术支持:丁丁网 dddazhe@hotmail.com & 2010-2020 All rights reserved