063-Goroutine
Posted --Allen--
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了063-Goroutine相关的知识,希望对你有一定的参考价值。
欢迎来到新的章节—— Goroutine & Channel.
如果说 goroutine 是 Golang 中的倚天剑,那 channel 就是 Golang 里的屠龙大宝刀。早在第一章,我们就展示过 gotoutine 和 channel 的魅力了,如果你忘记了,可以再次回顾一遍《goroutine 和 chan》。
我不会一遍又一遍的给你介绍 goroutine 的概念,一方面是因为你可能从未接触过协程,也不知道为什么有协程这个东西。难道仅仅是因为它比线程轻量吗?
其实要回答这个问题并不简单。只有在你充分了解并学习了异步 IO 编程的情况下,你才能感受到协程带来的便利性。没错,协程就是专为 IO 密集型服务器开发而生。
goroutine 可能和传统的协程概念并不完全一致,你可以认为它比协程更加灵活。协程往往是说运行在同一线程里的多条程序执行流。而 goroutine 是运行在多个线程上的多条程序执行流。
好了,为了不让你迷糊,上面这些概念你暂不用过多的去挖掘。相信我,慢慢你会掌握它的。
既然 goroutine 是 IO 密集型服务器的编程利器,那我们就从网络编程开始介绍它吧。
1. 并发服务器模型
学习过 steven 的 《unix 网络编程》,一定对网络编程不陌生。
如果你从未阅读或学习过这本书,强烈建议你去看看。Golang 并不是学习网络编程的最佳语言,只有 C 才是。从某种角度来说,使用 C 可以帮助你学习操作系统底层一些相关的原理和操作系统接口。如果你直接学习 Golang,这种过于高级的语言会帮你屏蔽掉太多的细节,其实对于你的学习并没有太多好处,充其量你也只是掌握了 Golang 的语法而已。
既然 C 语言这么牛逼,那为什么要用 Golang 而不用 C 来做服务器开发?在你充分掌握了网络编程技术细节后,使用 Golang 会让你如虎添翼,开发成本会大大降低。另外,使用 Golang 可以充分发挥机器性能。
有同学可能喜欢钻牛角尖,使用 C/C++ 难道就不能充分发挥机器性能吗?我只能说,这取决于你的编程水平。
假设我们还在使用 C/C++,要想解决并发问题,我们一般有下面几种解决方案:
- 多进程阻塞 IO 模型(一客户一进程,容易实现,并发程度低)
- 多线程阻塞 IO 模型(一客户一线程,容易实现,并发程度低)
- 单/多线程 IO 多路复用 + 非阻塞 IO (开发难度最大,并发度最高)
想想就觉得很头疼是不是?好了,再来看看 Golang 是怎么做的:
- 多协程阻塞 IO 模型(一客户一 goroutine,容易实现,并发程度高)
搞定。
简直爽爆了是不是?Golang 帮你搞定了太多的事情,屏蔽了太多的细节。你看,goroutine 既拥有多线程阻塞 IO 模型编写代码的便利性,也拥有 IO 多路复用 + 非阻塞 IO 的高并发特性,简直就是做服务器开发的同学们的福音。
2. echo server
echo server 简单吗?也许它很简单,也许一点也不简单。实现一个性能优异且没有 bug 的 echo server 更不简单。但是使用 golang,这就是一件轻而易举的事情。
首先来说说我们的 echo server 要支持什么功能:
- 使用 tcp 协议
- 客户端建立 tcp 长连接
- 客户端流式发送数据,服务器将数据原封不动将数据发送回客户端。
- 服务器能同时处理多个客户端的请求
下面是 Golang 版本的 echo server。不到 30 行,你就完成了一个高并发的 echo server。
package main
import (
"io"
"log"
"net"
)
func main()
listener, err := net.Listen("tcp", ":8001")
if err != nil
log.Fatal(err)
for
conn, err := listener.Accept()
if err != nil
log.Print(err)
continue
// 为客户端单独开一个协程
go handleConn(conn)
func handleConn(c net.Conn)
io.Copy(c, c)
c.Close()
怎么测试呢?其实很简单,你的 Linux 系统一般会默认带一个工具叫 netcat,它既可以作为服务器也可以作为客户端。这里我们只需要使用它的客户端功能就行了。
$ nc localhost 8001 # 连接上你的 echo server
hello # 输入 hello
hello # 返回 hello
^D # 按下 CTRL D 退出
$
3. 总结
- 掌握创建协程的语法
练习:写一个 Golang 版本的客户端,用来访问 echo server.
以上是关于063-Goroutine的主要内容,如果未能解决你的问题,请参考以下文章