Skip to content
shellhacks.dev
Go

Shrink a Go binary

Shrink a Go binary with -ldflags '-s -w', which drops the symbol table and the DWARF debug data. The size on disk falls, and stack traces still work.

1 min read
Summarize in AI

A small command line tool compiles to a binary of a few megabytes, and some of that is debugging data you do not ship.

main.goGo
package main

import "fmt"

func main() {
	fmt.Println("hello")
}
Shell
go build -o normal main.go
go build -ldflags '-s -w' -o small main.go
stat -c '%s %n' normal small
./small
Text
1822929 normal
1245184 small
hello

The linker flag -s omits the symbol table and -w omits the DWARF information, both listed in the linker documentation. Neither is needed to run the program, so the file is smaller, here from about 1.8 MB to 1.2 MB. A panic in the stripped binary still prints a readable stack trace, because Go keeps its own function tables for the runtime.

A stripped binary cannot be used with gdb or dlv for source level debugging, and profilers lose symbol names, so keep an unstripped build for diagnosing. The saving depends on what the program imports. Compressing with UPX saves more but makes the binary slower to start and is flagged by some scanners.

Share

More snippets

Go

Exit with a status

Exit with a status using os.Exit(n). It ends the program at once and skips every deferred call, so cleanup in defer is not run before the exit.

1 min read
Go

Raise the scanner line limit

Raise the line limit of bufio.Scanner with Buffer(make([]byte, 0, 64*1024), max). Lines over 64 KB otherwise stop the scan with token too long.

1 min read
Go

Set a timeout for a command

Stop a command that takes too long with exec.CommandContext and context.WithTimeout. In Go 1.19 a shell's child can keep Output() waiting past the deadline.

2 min read

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.