在 Web3 后端开发中,abigen 是一个至关重要的工具。它能根据 Solidity 合约生成的 ABI(应用二进制接口)自动生成 Go 语言代码,让你像调用普通 Go 函数一样调用智能合约。
以下是详细的 abigen 使用教程。
第一步:安装 abigen 工具
abigen 是 go-ethereum 项目的一部分。你可以通过以下命令安装:
1# 安装最新版 abigen 2go install github.com/ethereum/go-ethereum/cmd/abigen@latest 3
**验证安装:**在终端输入 abigen --version。如果看到版本号,说明安装成功。注意:如果提示找不到命令,请确保你的 $GOPATH/bin 已添加到系统的 PATH 环境变量中。
第二步:准备 Solidity 合约
创建一个简单的合约文件 SimpleStorage.sol:
1// SPDX-License-Identifier: MIT 2pragma uint256; 3pragma solidity ^0.8.0; 4 5contract SimpleStorage { 6 uint256 private data; 7 8 event DataStored(uint256 newValue); 9 10 function set(uint256 x) public { 11 data = x; 12 emit DataStored(x); 13 } 14 15 function get() public view returns (uint256) { 16 return data; 17 } 18} 19
第三步:获取 ABI 和 Bytecode
要生成 Go 代码,你需要两个东西:
- ABI: 描述合约有哪些函数。
- Bin (Bytecode): 合约的编译代码(如果你需要通过 Go 部署合约的话)。
方法 A:使用 solc 编译器(本地)
1solc --abi --bin SimpleStorage.sol -o build 2
方法 B:使用 Remix IDE(最简单)
- 将代码粘贴到 Remix。
- 编译合约。
- 在 "Compilation Details" 中点击 ABI 和 Bytecode 的复制按钮,分别存为
SimpleStorage.abi和SimpleStorage.bin。
第四步:使用 abigen 生成 Go 绑定
假设你现在有了 SimpleStorage.abi 和 SimpleStorage.bin,运行以下命令:
1abigen --abi SimpleStorage.abi --bin SimpleStorage.bin --pkg store --type SimpleStorage --out storage.go 2
参数解释:
--abi: 指定 ABI 文件路径。--bin: 指定 Bin 文件路径(可选,仅调用合约不部署时可不加)。--pkg: 指定生成的 Go 代码的包名(这里设为store)。--type: 指定生成的 Go 结构体的名称。--out: 指定输出的文件名。
生成成功后,你会看到一个几百行的 storage.go 文件,里面包含了 DeploySimpleStorage、Set、Get 等函数。
第五步:在 Go 代码中调用(实战例子)
现在我们要写一个 main.go 来调用这个生成的 storage.go。为了确保能跑通,我们连接到你之前的 Sepolia 测试网。
目录结构:
1. 2├── SimpleStorage.abi 3├── SimpleStorage.bin 4├── store/ 5│ └── storage.go // abigen 生成的文件 6├── main.go 7└── .env 8
main.go 实现代码:
1package main 2 3import ( 4 "context" 5 "fmt" 6 "log" 7 "math/big" 8 "os" 9 10 "go-wallet-lite/store" // 替换为你的项目路径/store 11 "github.com/ethereum/go-ethereum/accounts/abi/bind" 12 "github.com/ethereum/go-ethereum/common" 13 "github.com/ethereum/go-ethereum/ethclient" 14 "github.com/joho/godotenv" 15) 16 17func main() { 18 godotenv.Load() 19 20 // 1. 连接 Sepolia 节点 21 client, err := ethclient.Dial(os.Getenv("RPC_URL")) 22 if err != nil { 23 log.Fatal(err) 24 } 25 26 // 2. 准备合约地址 27 // 这是一个已经在 Sepolia 上部署好的测试合约地址(如果没有,可以换成你自己的) 28 contractAddr := common.HexToAddress("0x7de680214a1f335165c63e903b1e77983636f72a") 29 30 // 3. 实例化合约 31 instance, err := store.NewSimpleStorage(contractAddr, client) 32 if err != nil { 33 log.Fatal(err) 34 } 35 36 // 4. 调用 Read 方法 (Get) 37 // 查询合约里存的数字 38 value, err := instance.Get(&bind.CallOpts{}) 39 if err != nil { 40 log.Fatal(err) 41 } 42 fmt.Printf("当前合约存储的值: %s\n", value.String()) 43 44 // 5. 调用 Write 方法 (Set) 45 // 注意:写操作需要私钥签名,会消耗 Gas 46 /* 47 privateKey, err := crypto.HexToECDSA(os.Getenv("PRIVATE_KEY")) 48 auth, _ := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(11155111)) // Sepolia ChainID 49 50 tx, err := instance.Set(auth, big.NewInt(666)) // 将值设为 666 51 if err != nil { 52 log.Fatal(err) 53 } 54 fmt.Printf("交易已发送,Hash: %s\n", tx.Hash().Hex()) 55 */ 56} 57
常见坑点总结
- 包名不一致:
abigen生成时指定的--pkg store必须和文件夹名称store一致,否则 Go 找不到。 - ABI 更新不及时:如果你修改了 Solidity 代码,必须重新生成 ABI 并重新运行
abigen,否则调用时会报错(方法哈希不匹配)。 - 大数处理:Solidity 的
uint256在 Go 中对应的是*big.Int,不能直接用int,必须使用math/big库。 - ChainID:在做“写操作”时,
NewKeyedTransactorWithChainID里的 ChainID 必须传对(Sepolia 是11155111,主网是1)。
总结
abigen 的工作流就是:写合约 -> 拿 ABI -> 跑 abigen -> 在 Go 中像调包一样调合约。
建议尝试: 你可以先把 Get 方法跑通(不需要私钥),然后再尝试用私钥跑通 Set 方法。需要我教你如何在 Go 里安全地加载私钥吗?
《abigen使用教程 - go版本》 是转载文章,点击查看原文。