Golang blockieren und nicht blockieren

Ich bin etwas verwirrt darüber, wie Go mit nicht blockierenden E / A-Vorgängen umgeht. APIs sehen für mich zumeist synchron aus, und wenn Sie sich Präsentationen auf Go ansehen, ist es nicht ungewöhnlich, Kommentare wie "und die Aufrufblöcke" zu hören.

Wird beim Lesen aus Dateien oder dem Netzwerk die blockierende E / A verwendet? Oder gibt es irgendeine Art von Magie, die den Code neu schreibt, wenn er in einer Go-Routine verwendet wird?

Aus einem C # -Hintergrund kommend, fühlt sich dies sehr unintuitiv an. In C # haben wir dasawait Schlüsselwort, wenn asynchrone APIs verwendet werden. Dies zeigt deutlich, dass die API den aktuellen Thread liefern und später in einer Fortsetzung fortfahren kann.

So TLDR; Blockiert Go den aktuellen Thread, wenn IO innerhalb einer Go-Routine ausgeführt wird, oder wird er mithilfe von Fortsetzungen in eine C # -ähnliche asynchrone Wartestatusmaschine umgewandelt?