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)
}
}
}