Why viem-go
Learn why viem-go provides a better developer experience for Ethereum in Go
viem-go brings a modern, high-level Ethereum developer experience to the Go ecosystem — inspired by the architecture and abstractions pioneered by TypeScript viem.
If you want the deeper "how it works" view (call flows, package responsibilities, and where the benchmark wins come from), see Architecture.
Why viem-go?
- Go lacks high-level Ethereum abstractions: There isn't a widely adopted, high-level Ethereum API abstraction in the Go ecosystem that makes common tasks feel straightforward.
- go-ethereum is low-level by design: go-ethereum is excellent, but working directly with its lower-level APIs can be tedious and creates a higher barrier to entry for day-to-day EVM development in Go.
- viem is a familiar mental model: Many web3 developers already know viem's Client/Transport/Action patterns and are comfortable reading and writing that style of code.
- Bring viem's patterns to Go: viem-go takes the same composable abstractions (clients, transports, typed parameter structs) and adapts them into idiomatic Go to make EVM development more enjoyable.
- Unlock Go performance advantages: Go can address performance bottlenecks common in TypeScript workloads using concurrency and goroutines.
- High-level without sacrificing performance: viem-go aims to provide a high-level API without giving up performance relative to go-ethereum, and to build on efficiency advantages over TypeScript viem where possible.
Benchmarks
Benchmarks are run against the same Anvil instance (mainnet fork) for a fair comparison.
| Metric | Go (viem-go) | TypeScript (viem) |
|---|---|---|
| Geometric mean speedup | 7.12x | - |
| Avg ns/op | 2,020,982 | 10,567,395 |
| Avg ops/s | 495 | 95 |
| Wins | 59/59 | 0/59 |
See the Performance page for interactive charts, per-test analysis, and full results across all 9 suites.
Why Not Just Use go-ethereum?
go-ethereum is excellent for low-level operations, but it can be verbose for common tasks. viem-go provides higher-level abstractions while still using go-ethereum under the hood for cryptographic primitives.
1// Reading an ERC20 balance2result, _ := client.ReadContract(ctx, client.ReadContractOptions{3 Address: common.HexToAddress("0xA0b86991c..."),4 ABI: "[{"name":"balanceOf","type":"function",...}]",5 FunctionName: "balanceOf",6 Args: []any{ownerAddress},7})8balance := result.(*big.Int)
Design Principles
1. Mirror viem's API
When possible, viem-go uses the same function names, option structs, and patterns as viem. This makes it easy to translate examples and share knowledge between TypeScript and Go codebases.
2. Idiomatic Go
While mirroring viem, we embrace Go conventions:
- Explicit error handling (no panic)
- Context for cancellation
- Interfaces for flexibility
- Struct options instead of variadic params
context.Context as its first argument. Use context.WithTimeout or context.WithCancel to control request lifetimes and avoid hanging calls.3. Built on go-ethereum
viem-go doesn't reinvent cryptographic wheels. It uses go-ethereum for:
- Keccak256 hashing
- ECDSA signing
- ABI encoding/decoding
- RLP serialization
4. Comprehensive Testing
The test suite runs against actual Ethereum nodes (via Anvil) to ensure real-world compatibility.
What's Implemented
viem-go is under active development. Current features include:
Getting Started
Ready to dive in? Head to the Getting Started guide to set up your first viem-go project.