Coroutines in Kotlin are implemented in a different way than goroutines in Go, so which one is "faster" depends on the problem that you are solving and the kind of code you are writing.
In general, it is very hard to tell in advance which one is going to work better for a problem you have at hand. You have to run benchmarks for your particular workloads to figure it out. However, here is a general summary of key differences that should give you some guidance.
Kotlin coroutines require less memory per simple instance than Go goroutines. A simple coroutine in Kotlin occupies only a few dozen bytes of heap memory, while a Go goroutine starts with 4KiB of stack space. It means, that if you are planning to have literally millions of coroutines, then coroutines in Kotlin might give you an edge versus Go. It also makes Kotlin coroutines better suited for very short-lived and small tasks like generators and lazy sequences.
Kotlin coroutines can go to any stack depth, however each invocation of suspending function allocates object in heap for its stack. An invocation stack in Kotlin coroutines is currently implemented as a linked list of heap objects. In contrast, goroutines in Go use linear stack space. This makes suspension on deep stacks more efficient in Go. So, if the code you are writing suspends very deep down the stack, you may find that goroutines are more efficient for you.
Efficient asynchronous IO is a very multidimensional design problem. An approach that is efficient for one kind of application may not give the best performance to another one. All IO operations in Kotlin coroutines are implemented by libraries written in Kotlin or Java. There is a huge variety of IO libraries available to Kotlin code. In Go asynchronous IO is implemented by Go runtime using primitives that are not available to general Go code. If Go approach to implementing IO operations is well suited to your application, then you might find that its tight integration with Go runtime gives you an advantage. On the other side, in Kotlin you can find a library or write one yourself that implements asynchronous IO in a way that is best suited to your application.
Go runtime takes complete control of scheduling goroutines execution on the physical OS threads. The advantage of this approach is that you don't have to think about it all. With Kotlin coroutines you have fine-grained control on the execution environment of your coroutines. This is error-prone (e.g. you may simply create too many different thread-pools and waste your CPU time on context switching between them). However, it gives you ability to fine-tune your thread allocation and context switches for your application. For example, in Kotlin it is easy to execute your whole application or a subset of its code in a single OS thread (or thread pool) to completely avoid switching contexts between OS threads just by writing an appropriate code for that.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…