以太坊作为全球最大的智能合约平台,其庞大的生态系统吸引了大量开发者和企业,Go语言(Golang)凭借其高效的并发性能、简洁的语法和强大的标准库,成为与以太坊交互的热门选择,无论是构建去中心化应用(Dapp)的后端服务、开发自动化交易工具,还是实现链上数据的实时监控,Go都能为开发者提供高效、可靠的解决方案,本文将详细介绍如何使用Go语言与以太坊交互,涵盖环境搭建、连接节点、智能合约交互、交易发送等核心内容。
在开始Go与以太坊交互之前,需完成以下环境配置:
Go语言安装
从Go官网下载适合操作系统的安装包,安装后配置GOPATH和GOROOT环境变量,验证安装是否成功:

go version # 输出类似 "go version go1.21.0 linux/amd64"
以太坊节点选择
与以太坊交互需要连接到以太坊网络,开发者可选择以下方式:
https://mainnet.infura.io/v3/YOUR_PROJECT_ID 核心依赖库安装
Go语言中,与以太坊交互最常用的库是go-ethereum(又称ethereum-go),它提供了完整的以太坊JSON-RPC API封装,安装命令:
go get github.com/ethereum/go-ethereum go get github.com/ethereum/go-ethereum/common go get github.com/ethereum/go-ethereum/crypto go get github.com/ethereum/go-ethereum/ethclient
与以太坊交互的第一步是建立与节点的连接。go-ethereum的ethclient包提供了简洁的API,支持通过HTTP、WebSocket等方式连接节点。
以Infura远程节点为例,代码如下:

package main
import (
"context"
"fmt"
"log"
"github.com/ethereum/go-ethereum/ethclient"
)
func main() {
// 替换为你的Infura节点URL
nodeURL := "https://goerli.infura.io/v3/YOUR_PROJECT_ID"
client, err := ethclient.Dial(nodeURL)
if err != nil {
log.Fatalf("Failed to connect to the Ethereum network: %v", err)
}
defer client.Close()
// 验证连接是否成功
blockNumber, err := client.BlockNumber(context.Background())
if err != nil {
log.Fatalf("Failed to get block number: %v", err)
}
fmt.Printf("Connected to Ethereum network. Latest block number: %d\n", blockNumber)
}
运行后,若输出最新区块号,则表示连接成功。
WebSocket支持实时数据推送(如新区块、交易通知),适合需要实时监控的场景:
client, err := ethclient.Dial("wss://goerli.infura.io/ws/v3/YOUR_PROJECT_ID")
智能合约是以太坊的核心,Go语言可通过ABI(Application Binary Interface)与合约交互。
以简单的ERC20代币合约为例,需获取其ABI(通常为JSON格式),假设已编译合约得到ABI文件erc20.abi,可读取为[]byte类型。

若合约未部署,需先通过Go代码部署(需发送交易);若已部署,直接使用合约地址。
package main
import (
"context"
"fmt"
"log"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)
// 假设ERC20合约ABI(简化版)
var erc20ABI = `[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"type":"function"},...]`
func main() {
client, err := ethclient.Dial("https://goerli.infura.io/v3/YOUR_PROJECT_ID")
if err != nil {
log.Fatal(err)
}
// 合约地址(替换为实际部署的地址)
contractAddress := common.HexToAddress("0x123...456")
contract, err := bind.NewBoundContract(contractAddress, abi.JSON(strings.NewReader(erc20ABI)), client, client, client)
if err != nil {
log.Fatal(err)
}
// 调用view函数(无需交易)
var name string
err = contract.Call(&bind.CallOpts{}, &name, "name")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Token Name: %s\n", name)
// 调用非view函数(需发送交易,需先解锁账户)
// 假设账户私钥(实际应从安全存储读取)
privateKey, err := crypto.HexToECDSA("YOUR_PRIVATE_KEY")
if err != nil {
log.Fatal(err)
}
auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(5)) // Goerli链ID为5
if err != nil {
log.Fatal(err)
}
// 设置转账金额(1代币,假设18位小数)
amount := big.NewInt(1e18)
// 转账调用
tx, err := contract.Transact(auth, "transfer", common.HexToAddress("0xReceiver..."), amount)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Transfer transaction sent: %s\n", tx.Hash().Hex())
}
在以太坊网络中,任何状态变更操作(如转账、合约调用)都需要发送交易,并支付Gas费用。
通过bind.NewKeyedTransactorWithChainID创建交易发起者对象,设置nonce、gasLimit、gasPrice等参数:
auth := bind.NewKeyedTransactorWithChainID(privateKey, chainID) auth.Nonce = big.NewInt(getNonce(auth.From, client)) // 获取账户nonce auth.GasLimit = uint64(210000) // Gas限制 auth.GasPrice = big.NewInt(20000000000) // Gas价格(单位:wei)
Nonce是账户的交易计数器,必须按顺序递增,否则交易会被拒绝:
func getNonce(address common.Address, client *ethclient.Client) uint64 {
nonce, err := client.PendingNonceAt(context.Background(), address)
if err != nil {
log.Fatal(err)
}
return nonce
}
tx, err := client.TransferTokens(auth, recipient, amount)
if err != nil {
log.Fatal(err)
}
// 等待交易被打包
receipt, err := client.TransactionReceipt(context.Background(), tx.Hash())
if err != nil {
log.Fatal(err)
}
if receipt.Status == 1 {
fmt.Println("Transaction confirmed!")
} else {
fmt.Println("Transaction failed!")
}
智能合约事件可用于通知状态变更,Go可通过go-ethereum的ethclient.SubscribeNewHead或合约事件订阅功能监听事件。
package main
import (
"context"
"fmt"
"log"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/event"
)
// Transfer事件的结构体(需与合约ABI一致)
type Transfer struct {
From common.Address
To common.Address
Value *big.Int
}
func main() {
client, err := ethclient.Dial("wss://goerli.infura.io/ws/v3/YOUR_PROJECT_ID")
if err != nil {
log.Fatal(err)
}
// 合约地址
contractAddress := common.HexToAddress("0x123...456")
query := ethereum.FilterQuery{
Addresses: []common.Address{contractAddress},
Topics: [][]common.Hash{
{common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163
免责声明:本文为转载,非本网原创内容,不代表本网观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
如有疑问请发送邮件至:bangqikeconnect@gmail.com