生命不止,繼續 go go go !!!
golang就是為高併發而生的,為我們提供了goroutines和channel。雖然前面部落格的程式碼片段中也有用到這兩個關鍵字,但是一直沒有組織好語言,也沒有能力把goroutines和channel寫好,那麼估計我們先用,然後再看看的理解。
goroutinesA goroutine is a lightweight thread managed by the Go runtime.幾個關鍵字:輕量級,執行緒。
package mainimport ( "fmt" "time")func say(s string) { for i := 0; i < 5; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(s) }}func main() { go say("world") say("hello")}
區別:
f() // call f(); wait for it to return go f() // create a new goroutine that calls f(); don't wait12
channelsChannels are the pipes that connect concurrent goroutines.幾個關鍵字:管道 連線。
package mainimport "fmt"func main() { messages := make(chan string) go func() { messages <- "ping" }() msg := <-messages fmt.Println(msg)}
用了make宣告,時引用型別。
順序時鐘伺服器之前的部落格已經介紹了很多,如何使用net/http包來構建一個伺服器,關於golang中time package在昨天的部落格中也有介紹了。TCP 伺服器,直接上程式碼:
package mainimport ( "io" "log" "net" "time")func main() { listener, err := net.Listen("tcp", "localhost:8080") 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("2006-01-02 15:04:05\n")) if err != nil { return } time.Sleep(1 * time.Second) }}
然後go build即可。
nc命令介紹centos上安裝nc命令:
yum install nmap-ncat.x86_641
作用:(1)實現任意TCP/UDP埠的偵聽,nc可以作為server以TCP或UDP方式偵聽指定埠(2)埠的掃描,nc可以作為client發起TCP或UDP連線(3)機器之間傳輸檔案(4)機器之間網路測速
使用nc命令模擬client獲得伺服器時間後臺執行伺服器:
./clock &1
使用nc命令:
nc localhost 80801
輸出結果:2017-06-22 13:28:412017-06-22 13:28:422017-06-22 13:28:432017-06-22 13:28:442017-06-22 13:28:452017-06-22 13:28:462017-06-22 13:28:472017-06-22 13:28:482017-06-22 13:28:492017-06-22 13:28:502017-06-22 13:28:51….
這是個順序伺服器,如果多個客戶端連線的話,需要第一個結束後再執行第二個。
支援併發的始終伺服器很簡單,在上面的程式碼在handle中加入關鍵字go即可:
package mainimport ( "io" "log" "net" "time")func main() { listener, err := net.Listen("tcp", "localhost:8080") 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) { defer c.Close() for { _, err := io.WriteString(c, time.Now().Format("2006-01-02 15:04:05\n")) if err != nil { return } time.Sleep(1 * time.Second) }}
執行結果: