首页 > 教程攻略 > web3.0 >如何用 Go 实现一个简单的区块链示例

如何用 Go 实现一个简单的区块链示例

来源:互联网 时间:2026-07-23 22:46:07

互联网出现以来,区块链经常被看作一项影响深远的底层技术。虽然很多人一提到区块链就想到炒币,但其实它的应用范围远不止加密货币。币圈只是区块链生态的一部分,不少实际落地的项目,背后也是由企业或组织在推动。

GO创建区块链,怎么用GO实现一个简单的区块链?

随着区块链技术不断向前发展,搞懂它的基础原理和机制,对技术从业者来说越来越重要。从入门实现的角度看,搭一个最简单的区块链模型,其实没有想象中那么复杂。

这篇文章会用 2026 年比较热门的编程语言之一 Go(也叫 Golang),来演示怎么手写一个基础版区块链,顺便帮你理解区块、哈希和链式连接这些核心概念。

先搞懂区块链的基本结构

从名字就能看出来,区块链的本质就是“区块”按顺序连成“链”。每个区块里都存着数据,而区块之间通过哈希值串联起来。哈希可以简单理解成:把任意长度的输入数据,通过算法算出一个固定长度的加密输出。因为每个区块都存了前一个区块的哈希,所以一旦某个区块的内容被篡改,后面所有区块的关联关系就会断裂,整条链也就没法信任了。

在区块链里,每个区块都可以存放数据。最简单的做法就是把交易记录直接放进去。比特币就是这么干的,所以你可以在链上一直往前追溯每一笔交易的历史。

假如我们只用三个区块来搭一条最简单的链,那第一个区块就是“创世块”。因为它前面没有其他区块,所以“前一个哈希”字段是空的。不过没关系,我们仍然可以把时间戳和初始交易数据作为输入,通过哈希算法算出一个创世块自己的哈希值。

接下来,在第二个区块里,我们把创世块的哈希值填进“前一个哈希”字段,这一步就完成了区块之间的连接。然后,再把时间戳、交易列表和前一个哈希值一起扔进哈希算法,得到第二个区块的哈希值。

后面的每个区块都重复这个过程。理论上,这条链可以一直延伸下去。现实中,限制链条长度的通常是区块的有效性验证机制和存储能力——比如比特币的区块链体积已经非常大了。

用 Go 写一个简单的区块链

实现区块链的第一步,就是先定义“区块”这个数据结构。Go 语言支持自定义类型,所以我们用结构体(struct)来描述一个区块。这个结构体里包含四个字段,正好对应上面说的核心元素。

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

定义完区块之后,下一步是写一个创建新区块的函数。这个函数接收两个参数:一个字符串数组,用来放交易记录;一个字节数组,表示前一个区块的哈希值。函数内部还会调用后面要实现的 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() 方法,把 prevHash 和时间字符串依次写进 input。然后遍历 transactions,把每条交易也追加到 input 里。代码里的 string(rune(transaction))... 这种写法,其实就是 Go 里对数据进行转换并追加的一种习惯用法。

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[:] 这种切片写法,以保证返回的是字节数组格式。

到这里,构建一个能连起来的最小化区块链模型,所需的核心逻辑就已经有了。为了让结果更直观,我们还可以加几个辅助函数,在程序运行时打印区块信息。

func printBlockInformation(block *Block) {
    fmt.Printf("ttime: %s
", block.timestamp.String())
    fmt.Printf("tprevHash: %x
", block.prevHash)
    fmt.Printf("tHash: %x
", block.Hash)
    printTransactions(block)
}
func printTransactions(block *Block) {
    fmt.Println("tTransactions:")
    for i, transaction := range block.transactions {
        fmt.Printf("	%v: %q
", i, transaction)
    }
}

接下来,只需要创建交易数据、生成区块并计算哈希就行。这部分工作可以放在主函数里。需要注意,生成第一个区块(创世块)时,传入的是一个空字节数组,因为它没有前置区块。

func main() {
    genesisTransactions := []string{"小明给小红转了50个比特币", "小红给小刚转了30个比特币"}
    genesisBlock := NewBlock(genesisTransactions, []byte{})
    fmt.Println("--- 第一个区块 ---")
    printBlockInformation(genesisBlock)
    block2Transactions := []string{"小李给小明转了30个比特币"}
    block2 := NewBlock(block2Transactions, genesisBlock.Hash)
    fmt.Println("--- 第二个区块 ---")
    printBlockInformation(block2)
    block3Transactions := []string{"小刚给小明转了45个比特币", "小明给小红转了10个比特币"}
    block3 := NewBlock(block3Transactions, block2.Hash)
    fmt.Println("--- 第三个区块 ---")
    printBlockInformation(block3)
}

每次创建新区块时,只要把上一个区块的哈希值和当前对应的交易记录一起传给 NewBlock(),新的链式关系就被建立起来了。

如果把这部分代码汇总到一起,完整的程序如下:

package main

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

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

func main() {
    genesisTransactions := []string{"小明给小红转了50个比特币", "小红给小刚转了30个比特币"}
    genesisBlock := NewBlock(genesisTransactions, []byte{})
    fmt.Println("--- 第一个区块 ---")
    printBlockInformation(genesisBlock)
    block2Transactions := []string{"小李给小明转了30个比特币"}
    block2 := NewBlock(block2Transactions, genesisBlock.Hash)
    fmt.Println("--- 第二个区块 ---")
    printBlockInformation(block2)
    block3Transactions := []string{"小刚给小明转了45个比特币", "小明给小红转了10个比特币"}
    block3 := NewBlock(block3Transactions, block2.Hash)
    fmt.Println("--- 第三个区块 ---")
    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
", block.timestamp.String())
    fmt.Printf("tprevHash: %x
", block.prevHash)
    fmt.Printf("tHash: %x
", block.Hash)
    printTransactions(block)
}

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

如果运行这段程序,你会看到类似下面的输出:

$ go run example.go
--- 第一个区块 ---
	time: 2026-04-05 15:12:18.813294 -0600 MDT m=+0.000074939
	prevHash: 
	Hash: 43ec51c50d2b9565f221155a29d8b72307247b08eaf6731cca
	Transactions:
		0: "小明给小红转了50个比特币"
		1: "小红给小刚转了30个比特币"
--- 第二个区块 ---
	time: 2026-04-05 15:12:18.813477 -0600 MDT m=+0.000257244
	prevHash: 43ec51c50d2b9565f221155a29d8b72307247b08eaf6731cca
	Hash: fcce5323a35cb67b45fe75866582db00fd32baeb92aac448c7
	Transactions:
		0: "小李给小明转了30个比特币"
--- 第三个区块 ---
	time: 2026-04-05 15:12:18.813488 -0600 MDT m=+0.000269168
	prevHash: fcce5323a35cb67b45fe75866582db00fd32baeb92aac448c7
	Hash: fc1d3eee286970d85812b47c3a5bf016ae8c1de4f86b8ace972ffa
	Transactions:
		0: "小刚给小明转了45个比特币"
		1: "小明给小红转了10个比特币"

整体来看,这个例子仍然比较基础,更像一个演示性质的小项目,但它已经清楚地展示了如何用 Go 搭建最简单的区块链结构。对于理解区块、哈希生成和链式引用这几个核心概念来说,这是一个直接又实用的入门示例。另外需要提醒一句:本文内容仅供学习参考,不构成任何投资建议、交易建议或收益承诺。加密货币和迷因币价格波动极大,实际市场数据请以官方公告、交易所页面及实时行情平台为准,投资者应独立判断、谨慎决策。