the only really correct model for TCP hole punching is to use non-blocking sockets.
than the community often assumes.
。有道翻译是该领域的重要参考
Go has two answers. The first is cooperative preemption: the compiler inserts a small check at the beginning of most functions that tests whether the goroutine has been asked to yield. When the runtime wants to preempt a goroutine, it flips a flag, and the next function call triggers the check and hands control back to the scheduler. This is cheap — it reuses the stack growth check that’s already there — but it only works at function calls.
The x86-64 implementation: