這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。搜尋golang + epoll的例子,得到下面這段代碼,感覺golang的編程思維真正做到了並行編程:
package mainimport ("fmt""net""os""time")const (MAX_CONN_NUM = 5)//echo server Goroutinefunc EchoFunc(conn net.Conn) {defer conn.Close()buf := make([]byte, 1024)for {_, err := conn.Read(buf)if err != nil {//println("Error reading:", err.Error())return}//send reply_, err = conn.Write(buf)if err != nil {//println("Error send reply:", err.Error())return}}}//initial listener and runfunc main() {listener, err := net.Listen("tcp", "0.0.0.0:8088")if err != nil {fmt.Println("error listening:", err.Error())os.Exit(1)}defer listener.Close()fmt.Printf("running ...\n")var cur_conn_num int = 0conn_chan := make(chan net.Conn)ch_conn_change := make(chan int)go func() {for conn_change := range ch_conn_change {cur_conn_num += conn_change}}()go func() {for _ = range time.Tick(1e8) {fmt.Printf("cur conn num: %f\n", cur_conn_num)}}()for i := 0; i < MAX_CONN_NUM; i++ {go func() {for conn := range conn_chan {ch_conn_change <- 1EchoFunc(conn)ch_conn_change <- -1}}()}for {conn, err := listener.Accept()if err != nil {println("Error accept:", err.Error())return}conn_chan <- conn}}
再看這段代碼使用傳統思維實行方式:
////A echo server with max-connections limit and interval connection show//package mainimport ( "fmt" "net" "os" "time")const ( MAX_CONN_NUM = 5)//echo server Goroutinefunc EchoFunc(conn net.Conn, conn_close_flag chan int) { defer conn.Close() defer func() { conn_close_flag <- -1 }() buf := make([]byte, 1024) for { _, err := conn.Read(buf) if err != nil { //println("Error reading:", err.Error()) return } //send reply _, err = conn.Write(buf) if err != nil { //println("Error send reply:", err.Error()) return } }}//initial listener and runfunc main() { listener, err := net.Listen("tcp", "0.0.0.0:8088") if err != nil { println("error listening:", err.Error()) os.Exit(1) } defer listener.Close() fmt.Printf("running ...\n") var cur_conn_num float64 = 0 ch_conn_change := make(chan int, MAX_CONN_NUM) tick := time.Tick(1e8) for { //read all close flags berfor accept new connection //TODO: better code to handle batch close? readmore := 1 for readmore > 0 { select { case conn_change := <-ch_conn_change: cur_conn_num = cur_conn_num + float64(conn_change) default: readmore = 0 } } //FIXME: tick block by listener.Accept() select { case <-tick: fmt.Printf("cur conn num: %f\n", cur_conn_num) default: } if cur_conn_num >= MAX_CONN_NUM { //reach MAX_CONN_NUM, waiting for exist connection close time.Sleep(time.Second) } else { //accept new connetion conn, err := listener.Accept() if err != nil { println("Error accept:", err.Error()) return } cur_conn_num++ go EchoFunc(conn, ch_conn_change) } }}
這個案例中,golang通過多個goroutine + channel堵塞做到傳統的順序執行模式。
代碼來自google group的討論:https://groups.google.com/forum/#!topic/golang-china/q4pFH-AGnfs