Golang并发实践:goroutine and channel实现并发
发布于 2017-09-05 · 本文总共 1553 字 · 阅读大约需要
5 分钟
golang并发编程
golang有两种并发编程的风格:
1.使用goroutine和channel,支持CSP(Communicating Sequential Process); CSP是一种并发的模式,在不同的执行体(goroutine)之间传递值,但是变量本身局限于单一的执行体
2.共享内存
goroutine示例
package main
import (
"time"
"fmt"
)
func Fib() {
go spinner(100 * time.Millisecond)
const n = 45
fibN := fib(n)
fmt.Printf("\rFibonacci(%d) = %d\n", n , fibN)
}
func spinner(delay time.Duration){
for {
for _, r := range `-\|/`{
fmt.Printf("\r%c", r)
// fmt.Println(".", time.Now())
time.Sleep(delay)
}
}
}
func fib(x int) int{
if x < 2{
return x
}
return fib(x-1) + fib(x-2)
}
func main(){
Fib()
}
go run main.go Fibonacci(45) = 1134903170
main函数返回时,所有的goroutine都暴力地终结,然后程序退出;
goroutine示例:并发时钟服务器
实现一个顺序时钟服务,每秒一次的频率向客户端发送当前时间
package main
import (
"log"
"net"
"io"
"time"
)
func TcpTimer(){
listener, err := net.Listen("tcp", "localhost:8003")
if err != nil{
log.Fatal(err.Error())
}
for {
conn, err := listener.Accept()
if err != nil{
log.Print(err.Error())
continue
}
handleConn(conn)
}
}
func handleConn(conn net.Conn){
defer conn.Close()
for {
_, err := io.WriteString(conn, time.Now().Format("15:04:05\n"))
if err != nil{
return
}
time.Sleep(1 * time.Second)
}
}
func main(){
TcpTimer()
}
go build main.go ./main &
nc localhost 8003 18:27:39 18:27:40 18:27:41
使用go关键字支持并发:
for {
conn, err := listener.Accept()
if err != nil{
log.Print(err.Error())
continue
}
go handleConn(conn)
}
实现Golang版的netcat:
func NetCat() {
conn, err := net.Dial("tcp", "localhost:8003")
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)
}
}
go run main.go 18:36:07 18:36:08 18:36:09 18:36:10
go版本
go version go1.13.6 darwin/amd64
refs
《The Go Programming Language》Alan A.A, Donovan & Brian W.Kernighan