The Go runtime keeps track of the number of goroutines that are currently executing and ensures that this doesn't go above GOMAXPROCS. As soon as a goroutine enters a system call it is excluded from this count. If there aren't enough threads to run GOMAXPROCS goroutines the runtime may launch a new one.
See pkg/runtime/proc.c (entersyscall, ready, and matchmg).
See pkg/runtime/proc.c (entersyscall, ready, and matchmg).