1. 程式人生 > >golang基礎-chan的select操作、定時器操作、超時控制、goroutine中使用recover

golang基礎-chan的select操作、定時器操作、超時控制、goroutine中使用recover

chan的只讀和只寫

a.只讀chan的宣告
Var 變數的名字 <-chan int
Var readChan <- chan int

b. 只寫chan的宣告
Var 變數的名字 chan<- int
Var writeChan chan<- int

chan的select操作

格式如下

Select {
     case u := <- ch1:
     case e := <- ch2:
     default:   }

看例項程式碼:

package main

import "fmt"
import "time"
func main() { var ch chan int ch = make(chan int ,10) ch2:= make(chan int ,10) go func(){ var i int for { ch <- i time.Sleep(time.Second) ch2 <- i * i time.Sleep(time.Second) i ++ } }() for
{ select{ case v:= <-ch: fmt.Println(v) case v:= <-ch2: fmt.Println(v) default: fmt.Println("get data timeout") time.Sleep(time.Second) } } }

輸出如下:

PS E:\golang\go_pro\src\safly> go run demo.go
0
get data timeout 0 get data timeout 1 get data timeout 1 get data timeout 2 get data timeout 4 get data timeout 3 get data timeout 9 get data timeout 4 get data timeout 16 get data timeout 5 get data timeout exit status 2 PS E:\golang\go_pro\src\safly>

chan的定時器

package main

import "fmt"
import "time"

/*
type Ticker struct {
    C <-chan Time
    r runtimeTimer
}
*/

func main() {
    t := time.NewTicker(time.Second)
    for v := range t.C {
        fmt.Println("hello, ", v)
    }

}

輸出如下:

PS E:\golang\go_pro\src\safly> go run demo.go
hello,  2017-11-11 18:50:38.165007 +0800 CST
hello,  2017-11-11 18:50:39.1652525 +0800 CST
hello,  2017-11-11 18:50:40.165327 +0800 CST
hello,  2017-11-11 18:50:41.1650873 +0800 CST
exit status 2
PS E:\golang\go_pro\src\safly>

一次定時器

package main

import "fmt"
import "time"


/*
func After(d Duration) <-chan Time {
    return NewTimer(d).C
}
*/
func main() {
    select {
    case <- time.After(time.Second):
         fmt.Println("after")
    }
}

輸出如下:

PS E:\golang\go_pro\src\safly> go run demo.go
after
PS E:\golang\go_pro\src\safly>

超時控制

package main

import "fmt"
import "time"


func queryDb(ch chan int) {

        // time.Sleep(time.Second)
        ch <- 100
}


func main() {
    ch := make(chan int)
    go queryDb(ch)
    t := time.NewTicker(time.Second)

    select {
    case v := <-ch:
        fmt.Println("result", v)
    case <-t.C:
        fmt.Println("timeout")
    }

}

輸出如下:

PS E:\golang\go_pro\src\safly> go run demo.go
result 100
PS E:\golang\go_pro\src\safly>

以上程式碼是沒有超時的,我們將上面程式碼中 // time.Sleep(time.Second)註釋去掉
就會輸出如下的結果

PS E:\golang\go_pro\src\safly> go run demo.go
timeout
PS E:\golang\go_pro\src\safly>

goroutine中使用recover

應用場景,如果某個goroutine panic了,而且這個goroutine裡面沒有
捕獲(recover),那麼整個程序就會掛掉。所以,好的習慣是每當go產
生一個goroutine,就需要寫下recover

package main

import (
    "fmt"
    // "runtime"
    "time"
)

func test() {

    defer func() {
        if err := recover(); err != nil {
            fmt.Println("panic:", err)
        }
    }()

    var m map[string]int
    m["stu"] = 100

}

func calc() {
    for {
        fmt.Println("i'm calc")
        time.Sleep(time.Second)
    }
}

func main() {

    go test()
    for i := 0; i < 2; i++ {
        go calc()
    }

    time.Sleep(time.Second * 10000)
}

輸出如下:

PS E:\golang\go_pro\src\safly> go run demo.go
i'm calc
panic: assignment to entry in nil map
i'm calc
i'm calc
i'm calc
i'm calc
i'm calc
i'm calc
i'm calc
exit status 2
PS E:\golang\go_pro\src\safly>