Use runtime.GOMAXPROCS(0) to let Go automatically set the number of OS threads to match your machine's logical CPU cores, which is the recommended default for most applications. You should only manually set a specific value if you are running in a constrained environment (like a container with CPU limits) or need to tune performance for specific workloads.
In Go 1.5 and later, the runtime automatically detects available CPUs, so you rarely need to call this function at all. If you do need to change it, call it once at the very start of your main function before spawning any goroutines. The function returns the previous value, allowing you to save and restore settings if needed.
Here is a practical example of setting the limit explicitly for a CPU-bound task:
package main
import (
"fmt"
"runtime"
"sync"
)
func main() {
// Set GOMAXPROCS to 4 explicitly (or use 0 for auto-detection)
old := runtime.GOMAXPROCS(4)
fmt.Printf("Previous GOMAXPROCS: %d, New: %d\n", old, runtime.GOMAXPROCS(0))
var wg sync.WaitGroup
// Launch goroutines equal to the new GOMAXPROCS
for i := 0; i < runtime.GOMAXPROCS(0); i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
// CPU-bound work
sum := 0
for j := 0; j < 10000000; j++ {
sum += j
}
fmt.Printf("Goroutine %d done\n", id)
}(i)
}
wg.Wait()
}
If you are deploying to Kubernetes or Docker, the runtime usually respects the CPU limit set in the container spec automatically. However, if you encounter issues where the runtime doesn't see the limit correctly, you can force it:
# Run the binary with a specific limit via environment variable (Go 1.16+)
# Or set it in code if you need dynamic adjustment
GOMAXPROCS=2 ./my-app
Be careful not to set this value too high, as it can lead to excessive context switching and degraded performance. Conversely, setting it too low will underutilize your hardware. Always verify the current setting using runtime.GOMAXPROCS(0) (passing 0 returns the current value without changing it) during your startup logging.