当前位置: 首页 > 工具软件 > Bible Reader > 使用案例 >

Go语言圣经 - 第8章 Goroutines 和 Channels - 8.2 示例:并发的Clock服务

钮誉
2023-12-01

第8章 Goroutines 和 Channels

Go语言中的并发程序可以用两种手段来实现:goroutine 和 channel,其支持顺序通信进程,或被简称为CSP,CSP是一种并发编程模型,在这种并发编程模型中,值会在不同运行实例中传递,第二个手段便是多线程共享内存

8.2 示例:并发的Clock服务

网络编程是并发最适合的领域之一,最典型的是服务器要同时处理很多连接程序,我们来写个顺序执行的时钟服务器,让它每隔1秒钟将当前时间写到客户端

package main

import (
	"io"
	"log"
	"net"
	"time"
)

func main() {
	listener, err := net.Listen("tcp", "localhost:8000")
	if err != nil {
		log.Fatal(err)
	}
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Print(err)
			continue
		}
		handleConn(conn)
	}
}

func handleConn(c net.Conn) {
	defer c.Close()
	for {
		_, err := io.WriteString(c, time.Now().Format("15:04:05\n"))
		if err != nil {
			return // e.g., client disconnected
		}
		time.Sleep(1 * time.Second)
	}
}

我们创建了一个listener来监听网络端口到来的连接,然后用handleConn来处理这个完整的客户端连接,我们运行一下

xxx@MacBook-Pro-10 ~ % nc localhost 8000 
21:27:58
21:27:59
21:28:00
21:28:01
21:28:02
21:28:03

客户端将服务器发来的时间显示了出来,我们也可像下面这样改写一下代码

package main

import (
	"io"
	"log"
	"net"
	"os"
)

func main() {
	conn, err := net.Dial("tcp", "localhost:8000")
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
	mustCopy(os.Stdout, conn)
}

func mustCopy(dst io.Writer, src io.Reader) {

	if _, err := io.Copy(dst, src); err != nil {
		log.Fatal(err)
	}
}

我们现在同时在两个终端中运行测试,我们看到智能在一个终端中执行,也就是说第二个客户段必须等待第一个客户端完成才能进行

xxx@MacBook-Pro-10 ~ % ./netcat1
22:51:22
22:51:23
22:51:24
22:51:25
22:51:26
22:51:27
22:51:28
22:51:29
22:51:30
^C
xxx@MacBook-Pro-10 ~ % ./netcat1
22:52:20
22:52:21
22:52:22
22:52:23
22:52:24
22:52:25
22:52:26
22:52:27
^C

$ killall clock1

killall 命令是Unix命令行工具,可以杀掉指定名称的进程

现在我们把程序使用go关键字改成并发支持

for {
	conn,err := listener.Accept()
	if err != nil {
		log.Print(err)
		continue
	}	
	go handleConn(conn)
}

现在我们在多个终端中运行,它可以同时运行了

$ go build gopl.io/ch8/clock2
$ ./clock2 &
$ go build gopl.io/ch8/netcat1
$ ./netcat1
14:02:54                               $ ./netcat1
14:02:55                               14:02:55
14:02:56                               14:02:56
14:02:57                               ^C
14:02:58
14:02:59                               $ ./netcat1
14:03:00                               14:03:00
14:03:01                               14:03:01
^C                                     14:03:02
                                       ^C
$ killall clock2
 类似资料: