go-acme/tencentedgdeone: The Brute-Force Bash Script Defeating Go's Linker

How the maintainers of a popular Let's Encrypt client used regular expressions to rewrite a massive Tencent SDK, tricking the Go compiler into dropping megabytes of dead code.

6 min read • View on GitHub • More from go-acme

A massive monolithic stone block covered in runes, representing the official SDK, being cleanly sliced by a small, highly precise mechanical chisel to extract a single gear.
Extracting only the necessary components from a massive dependency.
Key Takeaways

The Hidden Cost of Cloud SDKs

Modern cloud SDKs are monolithic beasts. They are designed to support every conceivable API endpoint a provider offers. This comprehensiveness is a feature for enterprise applications, but it is a severe liability for lightweight CLI tools.

Consider lego, a popular Let's Encrypt client written in Go. Its users needed to automate certificate renewals for domains on Tencent EdgeOne nameservers.

I have a domain name activated on Tencent Edgeone using NS, but the original Tencent DNS cannot automatically renew the certificate. So i'd like to request to adaptation to Tencent Edgeone

Pimeng, User/Contributor · Issue #2604 · go-acme/lego

Fulfilling this request required importing the official Tencent Cloud API SDK. Doing so just to update a DNS record would pull in thousands of unrelated structures and methods. The resulting binary bloat was unacceptable for a tool prized for its portability.

Tricking the Tree-Shaker

The root of the problem lies in a specific quirk of the Go compiler. When developers write code using structural methods, the Go linker struggles to perform dead-code elimination.

If you import a Client struct and call just one of its fifty attached methods, the linker retains the entire structure and all fifty methods. The unused code is inextricably bound to the type.

The goal is to break the link between the Client structure and the other structures to reduce the binary size.

go-acme/tencentedgdeone README, Project Documentation · go-acme/tencentedgdeone

The solution is conceptually simple. You must sever the bond between the methods and the struct. By converting methods into standalone functions that simply accept the struct as a parameter, the linker can easily isolate and discard the unused functions.

Official SDK (Method Receivers)The Fork (Standalone Functions)
`func (c *Client) CreateInstance(req *Request)``func CreateInstance(c *Client, req *Request)`
Linker retains `Client` and all attached methods.Linker isolates the function. Unused functions are discarded.
High binary cost.Low binary cost.

The Regex Guillotine

Rewriting a massive SDK by hand is impossible. Using a graceful Go AST parser would be the conventional approach. The go-acme team chose neither.

Instead, they built an update script. This bash file is the beating heart of the repository. It relies on a ruthless sed command to perform a find-and-replace across the entire cloned SDK.

s/^func \(c \*Client\) ([A-Za-z0-9_]+)\((.*)\)/func \1(c *Client, \2)/

This regular expression acts as a bespoke compiler. It rewrites method receivers as function parameters and patches internal calls accordingly. It is incredibly fast and utterly devoid of nuance.

A heavy iron anchor representing unused code is chained to a rising hot air balloon representing the Go binary. Sharp shears representing the sed script snap the chain in half.
Breaking the structural type bond allows the compiler to drop dead code.

The Machine-Generated Loophole

Applying a brute-force regex to third-party code sounds like a recipe for disaster. Won't this script break the second Tencent updates their codebase?

The answer lies in the nature of the upstream codebase. The official Tencent SDK is entirely machine-generated. Because it consists of perfectly predictable boilerplate, a dumb text-processing tool like sed can reliably parse and modify it.

This fork is made for lego of tencentcloud/teo, and contains no other changes to the original code than the module name and method signatures.

go-acme/tencentedgdeone README, Project Documentation · go-acme/tencentedgdeone

This project is a masterclass in pragmatic engineering. Rather than waiting for Tencent to modularize their SDK, or accepting an enormous binary size, the maintainers built an automated pipeline to fix the dependency themselves. They turned a rigid monolith into a flexible toolkit, using nothing more than a bash script and a clever understanding of Go's compiler.