Делать ценностные суждения всегда сложно, поэтому я выделю три отличия. Вы сами решаете, попадут ли они в «за» или «против».
Хотя Go и async позволяют вам писать асинхронный код простым способом, в .NET вы должны знать, какая часть вашего кода асинхронна, а какая нет (то есть вы должны явно использовать Асинхронное / ожидание ключевых слов). В Go вам не нужно это знать - среда выполнения заставляет его «просто работать», специального синтаксиса для пометки асинхронного кода нет.
Дизайн Go не требует специального кода в стандартной библиотеке. .NET требует добавления нового кода в стандартную библиотеку для каждой асинхронной операции, существенно удваивая поверхность API для этих случаев, например, есть новый API для асинхронной загрузки http, и старый, не асинхронный API для загрузки http должен оставаться для обратной совместимости.
Разработка и реализация Go на несколько порядков проще. Небольшой фрагмент кода времени выполнения (планировщик) заботится о приостановке выполнения подпрограмм, блокирующих системные вызовы, и переходе в спящие режимы. В стандартной библиотеке не требуется никакой специальной асинхронной поддержки.
.NET реализация сначала требовала добавления вышеупомянутых новых API. Кроме того, реализация .NET основана на переписывании кода компилятором с помощью async / await в эквивалентные конечные автоматы. Это очень умно, но и довольно сложно. Практический результат состоял в том, что первая асинхронная CTP имела известные ошибки, в то время как реализация Go работала практически с самого начала.
В конце концов, это не имеет значения. async / await - лучший способ написать асинхронный код в .NET. Goroutines - лучший способ получить это в Go. Оба великолепны, особенно по сравнению с альтернативами в большинстве других языков.