Context #
声明 #
type Context interface { //接口
Deadline() (deadline time.Time, ok bool) //截止时间
Done() <-chan struct{} //协程是否结束,返回只读通道结构体
Err() error //错误信息,返回error类型
Value(key any) any //存储数据
}
数据传递 #
package main
import (
"context"
"fmt"
)
func main() {
ctx := context.Background()
ctx = context.WithValue(ctx, "access_token", "123")
GetUser(ctx)
}
func GetUser(ctx context.Context) {
accessToken := ctx.Value("access_token")
fmt.Println(accessToken)
}
取消协程 WithCancel #
可以假设这样一个场景,用户想要查看订单记录,开启查询一个协程,但这是一个耗时操作,所以可能会中途取消。用户取消了查询,那么这个协程就应该停止,how?
package main
import (
"context"
"fmt"
"sync"
"time"
)
var wait = sync.WaitGroup{}
func main() {
t := time.Now()
ctx, cancel := context.WithCancel(context.Background())
wait.Add(1)
go func() {
info, err := GetInfo(ctx)
fmt.Println(info, err)
}()
go func() {
time.Sleep(2 * time.Second)
cancel() // 取消
}()
wait.Wait()
fmt.Println(time.Since(t))
}
func GetInfo(ctx context.Context) (order []string, err error) {
go func() {
select {
case <-ctx.Done():
fmt.Println("Canceled")
err = ctx.Err()
wait.Done()
return
}
}()
time.Sleep(4 * time.Second) // 模拟耗时操作
wait.Done()
return []string{"a", "b", "c"}, nil
}
截止时间 WithDeadline #
package main
import (
"context"
"fmt"
"sync"
"time"
)
var wait = sync.WaitGroup{}
func main() {
t := time.Now()
ctx, _ := context.WithDeadline(context.Background(), time.Now().Add(3*time.Second))
wait.Add(1)
go func() {
info, err := GetInfo(ctx)
fmt.Println(info, err)
}()
//cancel() 可以手动调用cancel取消
wait.Wait()
fmt.Println(time.Since(t))
}
func GetInfo(ctx context.Context) (order []string, err error) {
go func() {
select {
case <-ctx.Done():
fmt.Println("Canceled")
err = ctx.Err()
wait.Done()
return
}
}()
time.Sleep(4 * time.Second) // 模拟耗时操作
wait.Done()
return []string{"a", "b", "c"}, nil
}
超时时间 WithTimeout #
package main
import (
"context"
"fmt"
"sync"
"time"
)
var wait = sync.WaitGroup{}
func main() {
t := time.Now()
ctx, _ := context.WithTimeout(context.Background(), 3*time.Second)
wait.Add(1)
go func() {
info, err := GetInfo(ctx)
fmt.Println(info, err)
}()
//cancel() 同样可以手动调用cancel取消
wait.Wait()
fmt.Println(time.Since(t))
}
func GetInfo(ctx context.Context) (order []string, err error) {
go func() {
select {
case <-ctx.Done():
fmt.Println("Canceled")
err = ctx.Err()
wait.Done()
return
}
}()
time.Sleep(4 * time.Second) // 模拟耗时操作
wait.Done()
return []string{"a", "b", "c"}, nil
}