### 内存占用
- 创建一个 goroutine 的栈内存消耗为 2 KB(Linux AMD64 Go v1.4后)，运行过程中，如果栈空间不够用，会自动进行扩容。
- 创建一个 thread 为了尽量避免极端情况下操作系统线程栈的溢出，默认会为其分配一个较大的栈内存( 1 - 8 MB 栈内存，POSIX Thread)，而且还需要一个被称为 “guard page” 的区域用于和其他 thread 的栈空间进行隔离。而栈内存空间一旦创建和初始化完成之后其大小就不能再有变化，这决定了在某些特殊场景下系统线程栈还是有溢出的风险。

### 创建和销毁
- 线程创建和销毀都会有巨大的消耗，是内核级的交互(trap)。进入内核所消耗的性能代价比较高，开销较大。
- goroutine 是用户态线程，是由 go runtime 管理，创建和销毁的消耗非常小。

### 调度切换
- 抛开陷入内核，线程切换会消耗 1000-1500 纳秒(上下文保存成本高，较多寄存器，公平性，复杂时间计算统计)，一个纳秒平均可以执行 12-18 条指令。所以由于线程切换，执行指令的条数会减少 12000-18000。
- goroutine 的切换约为 200 ns(用户态、3个寄存器)，相当于 2400-3600 条指令。因此，goroutines 切换成本比 threads 要小得多

### 复杂性
- 线程的创建和退出复杂，多个thread间通讯复杂(share memory)
- 不能大量创建线程，成本高，使用网络多路复用，存在大量callback。对于应用服务线程门槛高，例如需要做第三方库隔离，需要考虑引入线程池等