我正在使用Go编程语言处理云服务器的网络事务。 我遇到了一个问题,从不同的Goroutines同时读取相同的TCPconn 。
这是一个简单的例子
package main
import (
"fmt"
"net"
)
func main() {
addr, _ := net.ResolveTCPAddr("tcp", ":8888")
listener, _ := net.ListenTCP("tcp", addr)
for {
conn, err := listener.AcceptTCP()
if err != nil {
fmt.Println(err)
return
}
go Handle(conn) // output always coming from here
go Handle(conn)
}
}
func Handle(conn *net.TCPConn) {
data := make([]byte, 1024)
fmt.Println("Ok")
for {
len_data, err := conn.Read(data)
fmt.Println(err)
fmt.Println(len_data)
}
}
在此示例中,控制台输出始终来自第一个goroutine go Handle(conn)
...
如何同时从2个Goroutines进行读取功能?
由于
答案 0 :(得分:1)
一种方法是使用io.MultiWriter
和io.Pipe
:
func main() {
var wg sync.WaitGroup
r := strings.NewReader(hello)
pr1, pw1 := io.Pipe()
pr2, pw2 := io.Pipe()
pr3, pw3 := io.Pipe()
mw := io.MultiWriter(pw1, pw2, pw3)
wg.Add(4)
go process(&wg, 0, pr1)
go process(&wg, 1, pr2)
go process(&wg, 2, pr3)
go func() {
io.Copy(mw, r)
pw1.Close()
pw2.Close()
pw3.Close()
wg.Done()
}()
wg.Wait()
}
答案 1 :(得分:0)
启动单个go例程以执行conn.Read(data)并将结果放入通道。
然后(同时,无需等待第一个例行程序完成)启动多个例程以从该频道读取。
你不想直接从多个go例程中读取conn,因为它不是线程安全的(事实上它运行,并且只能在单个go例程上运行,可能是因为你的MAXGOPROCS == 1)
答案 2 :(得分:-1)
好的,首先。你做错了朋友。
您应该做的是创建工作人员(预创建),创建频道并使用传入连接聚合该频道。比你应该在工人内部采取相同的连接并处理它。通过这种方式,您将获得针对您的连接运行的X并发工作程序。
我继续向你写了一个很好的例子,说明如何优雅地处理工人,但没有时间写下如何优雅地处理传入的连接。从来没有,你会明白我的意思。
http://play.golang.org/p/YkQVmBEWly
希望这有帮助,