go context
go context
context是go语言中用来在协程中传递数据的,也可以用来停止协程
1、数据传递
context可以传递各种数据,例如字节,字符串,结构体等等
使用Withvalue来设置键值对
package main
import (
"context"
"fmt"
)
type User struct {
Name string
}
func main() {
// 创建一个空的context
ctx := context.Background()
// 设置键值对
ctx = context.WithValue(ctx, "name", "xiaoxie")
ctx = context.WithValue(ctx, "user", User{
Name: "xiaoyang",
})
GetUser(ctx)
}
func GetUser(ctx context.Context) {
// 获取context中的键值对数据
fmt.Println(ctx.Value("name"))
// 可以进行断言处理
fmt.Println(ctx.Value("user").(User).Name)
}
2、取消协程
在运行过程中,用户可能随时取消一个耗时的请求操作,所以我们需要提供给用户一个取消协程的接口
没有取消协程的操作只能等待
package main
import (
"context"
"fmt"
"sync"
"time"
)
var waitGroup = sync.WaitGroup{}
func main() {
waitGroup.Add(1)
t1 := time.Now()
go func() {
info, err := GetIP(context.Background())
fmt.Println(info, err)
waitGroup.Done()
}()
waitGroup.Wait()
fmt.Println("执行完成", time.Since(t1))
}
func GetIP(ctx context.Context) (string, error) {
// 模拟耗时的操作
time.Sleep(4 * time.Second)
// 模拟请求的内容
return "localhost", nil
}
输出内容
localhost <nil>
执行完成 4.0064976s
实现取消协程
package main
import (
"context"
"fmt"
"sync"
"time"
)
var waitGroup = sync.WaitGroup{}
func main() {
waitGroup.Add(1)
ctx, cancel := context.WithCancel(context.Background())
t1 := time.Now()
go func() {
info, err := GetIP(ctx)
fmt.Println(info, err)
waitGroup.Done()
}()
go func() {
// 假设过了两秒用户取消协程
time.Sleep(2 * time.Second)
cancel()
}()
waitGroup.Wait()
fmt.Println("执行完成", time.Since(t1))
}
func GetIP(ctx context.Context) (string, error) {
// 监听
go func() {
select {
case <-ctx.Done():
err := ctx.Err()
fmt.Println("协程取消", err)
waitGroup.Done()
return
}
}()
time.Sleep(4 * time.Second)
waitGroup.Done()
return "localhost", nil
}
输出:
协程取消 context canceled
执行完成 2.003113s
3、截止时间、超时时间
context可以主动取消,也可以根据截止时间或者超时时间来取消
截止时间
设置一个截止的时间点
package main
import (
"context"
"fmt"
"sync"
"time"
)
var waitGroup = sync.WaitGroup{}
func main() {
waitGroup.Add(1)
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(2*time.Second))
defer cancel()
t1 := time.Now()
go func() {
info, err := GetIP(ctx)
fmt.Println(info, err)
waitGroup.Done()
}()
waitGroup.Wait()
fmt.Println("执行完成", time.Since(t1))
}
func GetIP(ctx context.Context) (string, error) {
// 监听
go func() {
select {
case <-ctx.Done():
err := ctx.Err()
fmt.Println("截止时间已到", err)
waitGroup.Done()
return
}
}()
// 模拟耗时的操作
time.Sleep(4 * time.Second)
waitGroup.Done()
// 模拟请求的内容
return "localhost", nil
}
截止时间已到 context deadline exceeded
执行完成 2.0086572s
超时时间
设置一个超时的时长,其余代码部分基本一致
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)

浙公网安备 33010602011771号