golang context

ex1

package main

import (    
    "fmt"
)

// 最佳context 實踐
//  Context 目標是實現各個goroutine能及時終止退出。


func main() {
    // Basic ipfsnode setup 
    a := 10
    fmt.Println("hhha")
    fmt.Println(a)  
}

ex2

package main

import "fmt"

// 打印輸出, 發送數據到通道
func printHello(ch chan int) {
    fmt.Println("Hello from printHello")
    // 發送一個數據到通道
    ch <- 2
}

func main() {
    /*
    使用make函數,建立一個通道。
    通道是能夠帶緩衝的, 若是你指定了長度。如ch := make(chan int, 2)

    channel可分爲三種類型:
        只讀channel:只能讀channel裏面數據,不可寫入
        只寫channel:只能寫數據,不可讀
        通常channel:可讀可寫
    */
    ch := make(chan int)
    //內聯goroutine. 定義一個函數,直接go調用.
    //結束時,往通道發一個數據做爲信號
    go func(){
        fmt.Println("Hello inline")
        //send a value on channel
        ch <- 1
    }()
    //調用一個函數做爲 goroutine
    go printHello(ch)
    fmt.Println("Hello from main")

    //首先從通道中取出一個數據, 並賦值給變量,並打印出來
    i := <- ch
    fmt.Println("Recieved ",i)
    //從通道獲取第二個數據
    // 若是不須要它, 能夠不賦值給變量
    <- ch
}

ex3

/*
context(上下文): 能夠理解爲timeout(超時), deadline(終止時間線), 或者一個channel(通道)來指示goroutine中止工做並退出
好比,在系統中, 當調用其它網站的接口時,一般速度比較慢, 可是你又依賴它的及時返回, 因此並不打算把這個進行備份請求。 一般會設置一個超時。
*/


/* 結構以下
// deadline終止時間線, cancelation 取消信號, and request-scoped 請求範圍值
// 多個goroutines同時使用,是安全的
type Context interface {
    // Done 方法在Context被取消或超時時返回一個close的channel,close的channel能夠做爲廣播通知,告訴給context相關的函數要中止當前工做而後返回。
    // 當一個父operation啓動一個goroutine用於子operation,這些子operation不可以取消父operation。下面描述的WithCancel函數提供一種方式能夠取消新建立的Context.
    // Context能夠安全的被多個goroutine使用。開發者能夠把一個Context傳遞給任意多個goroutine而後cancel這個context的時候就可以通知到全部的goroutine。
    Done() <-chan struct{}

    // Err方法返回context爲何被取消。
    Err() error

    // Deadline返回context什麼時候會超時。
    Deadline() (deadline time.Time, ok bool)

    // Value返回context相關的數據。
    Value(key interface{}) interface{}
}
*/
// 建立context上下文


// 1. context.Backgrond() ctx Context
// BackGound是全部Context的root,不可以被cancel。
// 這個函數返回一個空的上下文, 這個僅在高層使用(如在main 或者 頂級請求)


/* 2. WithCancel返回一個繼承的Context,這個Context在父Context的Done被關閉時關閉本身的Done通道,或者在本身被Cancel的時候關閉本身的Done。
      WithCancel同時還返回一個取消函數cancel,這個cancel用於取消當前的Context。
*/

package main

import (
    "context"
    "log"
    "os"
    "time"
)

var logg *log.Logger

func someHandler() {
    ctx, cancel := context.WithCancel(context.Background())
    go doStuff(ctx)

    //10秒後取消doStuff
    time.Sleep(10 * time.Second)
    cancel()

}

//每1秒work一下,同時會判斷ctx是否被取消了,若是是就退出
func doStuff(ctx context.Context) {
    for {
        time.Sleep(1 * time.Second)
        select {
        case <-ctx.Done():
            logg.Printf("done")
            return
        default:
            logg.Printf("work")
        }
    }
}

func main() {
    logg = log.New(os.Stdout, "", log.Ltime)
    someHandler()
    logg.Printf("down")
}

ex4

/*
context(上下文):
withDeadline withTimeout
*/


/* 結構以下
// deadline終止時間線, cancelation 取消信號, and request-scoped 請求範圍值
// 多個goroutines同時使用,是安全的
type Context interface {
    // Done 方法在Context被取消或超時時返回一個close的channel,close的channel能夠做爲廣播通知,告訴給context相關的函數要中止當前工做而後返回。
    // 當一個父operation啓動一個goroutine用於子operation,這些子operation不可以取消父operation。下面描述的WithCancel函數提供一種方式能夠取消新建立的Context.
    // Context能夠安全的被多個goroutine使用。開發者能夠把一個Context傳遞給任意多個goroutine而後cancel這個context的時候就可以通知到全部的goroutine。
    Done() <-chan struct{}

    // Err方法返回context爲何被取消。
    Err() error

    // Deadline返回context什麼時候會超時。
    Deadline() (deadline time.Time, ok bool)

    // Value返回context相關的數據。
    Value(key interface{}) interface{}
}
*/
package main

import (
    "context"
    "log"
    "os"
    "time"
)

var logg *log.Logger

//每1秒work一下,同時會判斷ctx是否被取消了,若是是就退出
func doStuff(ctx context.Context) {
    for {
        time.Sleep(1 * time.Second)
        select {
        case <-ctx.Done():
            logg.Printf("done")
            return
        default:
            logg.Printf("work")
        }
    }
}
func timeoutHandler() {
    // 這裏在上下文中加入了超時限制, 超時和取消,取其短。
    ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(2 * time.Second))
    go doStuff(ctx)
    time.Sleep(10 * time.Second)
    cancel()
}

func main() {
    logg = log.New(os.Stdout, "", log.Ltime)
    timeoutHandler()
    logg.Printf("end")
}

ex5

/*
context(上下文):
withDeadline withTimeout
*/


/* 結構以下
// deadline終止時間線, cancelation 取消信號, and request-scoped 請求範圍值
// 多個goroutines同時使用,是安全的
type Context interface {
    // Done 方法在Context被取消或超時時返回一個close的channel,close的channel能夠做爲廣播通知,告訴給context相關的函數要中止當前工做而後返回。
    // 當一個父operation啓動一個goroutine用於子operation,這些子operation不可以取消父operation。下面描述的WithCancel函數提供一種方式能夠取消新建立的Context.
    // Context能夠安全的被多個goroutine使用。開發者能夠把一個Context傳遞給任意多個goroutine而後cancel這個context的時候就可以通知到全部的goroutine。
    Done() <-chan struct{}

    // Err方法返回context爲何被取消。
    Err() error

    // Deadline返回context什麼時候會超時。
    Deadline() (deadline time.Time, ok bool)

    // Value返回context相關的數據。
    Value(key interface{}) interface{}
}
*/
package main

import (
    "context"
    "log"
    "os"
    "time"
)

var logg *log.Logger

//每1秒work一下,同時會判斷ctx是否被取消了,若是是就退出
func doStuff(ctx context.Context) {
    for {
        time.Sleep(1 * time.Second)
        select {
        case <-ctx.Done():
            logg.Printf("done")
            return
        default:
            logg.Printf("work")
        }
    }
}
func doTimeOutStuff(ctx context.Context) {
    for {
        time.Sleep(1 * time.Second)

        if deadline, ok := ctx.Deadline(); ok { //設置了deadl
            logg.Printf("deadline set")
            if time.Now().After(deadline) {
                logg.Printf(ctx.Err().Error())
                return
            }

        }

        select {
        case <-ctx.Done():
            logg.Printf("done")
            return
        default:
            logg.Printf("work")
        }
    }
}

func timeoutHandler() {
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    // ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(5*time.Second))
    go doTimeOutStuff(ctx)
    // go doStuff(ctx)

    time.Sleep(10 * time.Second)

    cancel()

}

func main() {
    logg = log.New(os.Stdout, "", log.Ltime)
    timeoutHandler()
    logg.Printf("end")
}

ex6

/*
context(上下文):
withValue 附加一些(不可變)數據, 供派生goroutine查詢用
*/

package main

import (
    "context"
    "log"
    "os"
    "time"
)

const (
    GOLABLE_KEY = "test123"
)

func main() {
    //父context控制子context
    controlAllConrrent()
}

func controlAllConrrent() {

    logg := log.New(os.Stdout, "", log.Ltime)
    handleSome()
    logg.Println("over ")
}

//父協程
func handleSome() {
    //ctx, cancelFunc := context.WithCancel(context.Background())
    //ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*2)
    ctx, cancelFunc := context.WithDeadline(context.Background(), time.Now().Add(time.Second*2))

    ctx = context.WithValue(ctx, GOLABLE_KEY, "1234")

    go workerFunc(ctx, "str1")
    go workerFunc(ctx, "str2")
    time.Sleep(time.Second * 3)
    cancelFunc()
}

//子協程
func workerFunc(ctx context.Context, showStr string) {
    for {
        time.Sleep(time.Second * 1)
        select {
        case <-ctx.Done():
            log.Println("done")
            return
        default:
            val123 := ctx.Value(GOLABLE_KEY).(string)
            log.Println(val123, showStr)
        }
    }
}
相關文章
相關標籤/搜索