有人能帮忙解释一下下面的代码片段是什么意思吗?
var partner = make(chan io.ReadWriteCloser)
func match(c io.ReadWriteCloser) {
fmt.Fprintln(c, "Waiting for a partner...")
select {
case partner <- c:
// handled by the other goroutine
case p := <-partner:
chat(p, c)
}
}
完整版本:
package main
import (
"fmt"
"golang.org/x/net/websocket"
"html/template"
"io"
"log"
"net/http"
)
const listenAddr = "localhost:4000"
type socket struct {
conn *websocket.Conn
done chan bool
}
func (s socket) Read(b []byte) (int, error) {
return s.conn.Read(b)
}
func (s socket) Write(b []byte) (int, error) {
return s.conn.Write(b)
}
func (s socket) Close() error {
s.done <- true
return nil
}
var rootTemplate = template.Must(template.New("root").Parse(`
<!DOCTYPE html>
<html>
<head>
<title>Websocket Chat - Golang</title>
<meta charset="UTF-8"/>
<script>
var input, output, websocket;
function showMessage(msg) {
var p = document.createElement("p");
p.innerHTML = msg;
output.appendChild(p);
}
function onMessage(e) {
showMessage(e.data);
}
function onClose() {
showMessage("Connection closed.");
}
function onKeyUp(e) {
if (e.keyCode === 13) {
sendMessage();
}
}
function sendMessage() {
var msg = input.value;
input.value = "";
websocket.send(msg + "\n");
showMessage(msg);
}
function init() {
input = document.getElementById("input");
input.addEventListener("keyup", onKeyUp, false);
output = document.getElementById("output");
websocket = new WebSocket("ws://{{.}}/socket");
websocket.onmessage = onMessage;
websocket.onclose = onClose;
}
window.addEventListener("load", init);
</script>
</head>
<body>
Say: <input id="input" type="text"/>
<div id="output"></div>
</body>
</html>
`))
func rootHandler(w http.ResponseWriter, r *http.Request) {
rootTemplate.Execute(w, listenAddr)
}
func socketHandler(conn *websocket.Conn) {
s := socket{conn: conn, done: make(chan bool)}
go match(s)
<-s.done
}
var partner = make(chan io.ReadWriteCloser)
func match(c io.ReadWriteCloser) {
fmt.Fprintln(c, "Waiting for a partner...")
select {
case partner <- c:
// handled by the other goroutine
case p := <-partner:
chat(p, c)
}
}
func chat(a, b io.ReadWriteCloser) {
fmt.Fprintln(a, "Found one! Say hi.")
fmt.Fprintln(b, "Found one! Say hi.")
errc := make(chan error, 1)
go cp(a, b, errc)
go cp(b, a, errc)
if err := <-errc; err != nil {
log.Println(err)
}
a.Close()
b.Close()
go io.Copy(b, a)
io.Copy(a, b)
}
func cp(w io.Writer, r io.Reader, errc chan<- error) {
_, err := io.Copy(w, r)
errc <- err
}
func main() {
http.HandleFunc("/", rootHandler)
http.Handle("/socket", websocket.Handler(socketHandler))
err := http.ListenAndServe(listenAddr, nil)
if err != nil {
log.Fatal(err)
}
}
不太明白为什么这个聊天功能可以执行时,第二个加入者加入聊天频道。
1条答案
按热度按时间ars1skjm1#
看起来HTTP处理程序创建了一个Web Socket,并开始等待另一方连接。这是因为当处理HTTP请求时,处理程序调用
match
,它将在select
上阻塞,因为partner
通道既不可读也不可写。没有goroutine监听它,或者发送给它。当第二个请求到来时,
match
再次被另一个goroutine调用。现在有两个goroutine,它们可以 * 匹配 *。其中一个goroutine可以发送到partner
通道,另一个接收它。传输的对象是读写器,然后用于两个伙伴之间的通信。