Go语言中如何解析ethTypes.Log日志为自定义结构体?
解析以太坊日志到Go结构体方案
针对你用go-ethereum获取到的[]ethTypes.Log日志,要解析成对应MyEvent的结构体,按以下步骤操作:
1. 定义匹配事件参数的结构体
根据你的事件签名MyEvent(uint8,bytes32,uint64,address,bytes,bytes),定义对应的Go结构体,注意Solidity类型和Go类型的映射:
import "github.com/ethereum/go-ethereum/common" type MyEvent struct { Param1 uint8 Param2 [32]byte Param3 uint64 Param4 common.Address Param5 []byte Param6 []byte }
2. 准备事件ABI并初始化ABI实例
你需要先获取合约的ABI(如果有完整ABI最好,也可以只提取该事件的ABI片段),比如该事件的ABI片段可写为:
[ { "anonymous": false, "inputs": [ {"indexed": false, "name": "", "type": "uint8"}, {"indexed": false, "name": "", "type": "bytes32"}, {"indexed": false, "name": "", "type": "uint64"}, {"indexed": false, "name": "", "type": "address"}, {"indexed": false, "name": "", "type": "bytes"}, {"indexed": false, "name": "", "type": "bytes"} ], "name": "MyEvent", "type": "event" } ]
然后在代码里初始化ABI实例:
import ( "bytes" "github.com/ethereum/go-ethereum/accounts/abi" ) // 将ABI字符串转为字节数组 abiBytes := []byte(`[{"anonymous":false,"inputs":[{"indexed":false,"name":"","type":"uint8"},{"indexed":false,"name":"","type":"bytes32"},{"indexed":false,"name":"","type":"uint64"},{"indexed":false,"name":"","type":"address"},{"indexed":false,"name":"","type":"bytes"},{"indexed":false,"name":"","type":"bytes"}],"name":"MyEvent","type":"event"}]`) eventABI, err := abi.JSON(bytes.NewReader(abiBytes)) if err != nil { panic(err) }
3. 遍历日志并解析到结构体
遍历你获取到的logs数组,对每个日志调用UnpackIntoInterface方法解析:
import "fmt" for _, log := range logs { var event MyEvent // 解析日志数据到结构体 err := eventABI.UnpackIntoInterface(&event, "MyEvent", log.Data) if err != nil { // 处理解析错误,比如跳过该日志或打印错误 fmt.Printf("解析日志失败: %v\n", err) continue } // 若事件有indexed参数,需从log.Topics提取(第一个topic是事件签名哈希),你的事件无indexed参数可跳过此步 // 此时event已包含所有触发数据,可直接使用 fmt.Printf("解析到事件: %+v\n", event) }
注意事项
- 结构体字段顺序必须和事件参数顺序完全一致,
abi.Unpack按顺序匹配,与字段名无关。 - 如果有完整合约ABI文件,可直接读取文件内容初始化ABI实例,无需手动编写片段。
- 若事件含
indexed参数,需额外从log.Topics中提取对应数据并赋值到结构体字段。
内容的提问来源于stack exchange,提问作者pastrn
相关产品推荐
相关产品推荐

