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)
}
}
}
golang context的更多相关文章
- Golang Context 详细介绍
Golang context 本文包含对context实现上的分析和使用方式,分析部分源码讲解比价多,可能会比较枯燥,读者可以直接跳过去阅读使用部分. ps: 作者本着开源分享的精神撰写本篇文章,如果 ...
- Golang Context 包详解
Golang Context 包详解 0. 引言 在 Go 语言编写的服务器程序中,服务器通常要为每个 HTTP 请求创建一个 goroutine 以并发地处理业务.同时,这个 goroutine 也 ...
- 带小伙伴手写 golang context
前言 - context 源码 可以先了解官方 context.go 轮廓. 这里捎带保存一份当前 context 版本备份. // Copyright 2014 The Go Authors. Al ...
- golang context学习记录1
1.前言 一个请求,可能涉及多个API调用,多个goroutine,如何在多个API 之间,以及多个goroutine之间协作和传递信息,就是一个问题. 比如一个网络请求Request,需要开启一些g ...
- Golang Context 的原理与实战
本文让我们一起来学习 golang Context 的使用和标准库中的Context的实现. golang context 包 一开始只是 Google 内部使用的一个 Golang 包,在 Gola ...
- 【GoLang】golang context channel 详解
代码示例: package main import ( "fmt" "time" "golang.org/x/net/context" ) ...
- Golang context包解读
Context 通常被译作 上下文 ,一般理解为程序单元的一个运行状态.现场.快照,而翻译中 上下 又很好地诠释了其本质,上下上下则是存在上下层的传递, 上 会把内容传递给 下 . 在Go语言中,程序 ...
- golang context 剖析 1.7.4 版本
1. 内部结构之 - timerCtx . type timerCtx struct { cancelCtx timer *time.Timer // Under cancelCtx.mu. dead ...
- golang Context for goroutines
概要 goroutine 的控制 取消控制 超时控制 goroutine 之间的传值 总结 概要 golang 的提供的 channel 机制是基于 CSP(Communicating Sequenc ...
- golang context包
go context标准库 context包在Go1.7版本时加入到标准库中.其设计目标是给Golang提供一个标准接口来给其他任务发送取消信号和传递数据.其具体作用为: 可以通过context发送取 ...
随机推荐
- wcf在post请求时,关于string类型参数传入中文的处理
一.方法默认只有一个参数 (1)BodyStyle = WebMessageBodyStyle.Bare [OperationContract][WebInvoke(Method = "PO ...
- NPM 报错--fs: re-evaluating native module sources is not supported. If you are using the graceful-fs module
fs: re-evaluating native module sources is not supported. If you are using the graceful-fs module 解决 ...
- 八大排序算法——归并排序(动图演示 思路分析 实例代码java 复杂度分析)
一.动图演示 二.思路分析 归并排序就是递归得将原始数组递归对半分隔,直到不能再分(只剩下一个元素)后,开始从最小的数组向上归并排序 1. 向上归并排序的时候,需要一个暂存数组用来排序, 2. 将 ...
- 使用有序GUID:提升其在各数据库中作为主键时的性能
原文出处:https://www.codeproject.com/articles/388157/guids-as-fast-primary-keys-under-multiple-database ...
- 怎样用div做三角形
20181204 用盒子模型做三角形的效果: <div></div> width:0px; height:0px; border:10px solid red; border- ...
- Android Studio之SVN打分支、切换分支及合并分支
1.打分支: 右击项目--Subversion--Branch or Tag 点击OK,分支就创建成功了,接下来我们切换到分支v2 2.切换分支: 右击项目--Subversion--Update D ...
- 使用labelme制作自己的数据集
# python3 conda create --name=labelme python=3.6 source activate labelme # conda install -c conda-fo ...
- SoapUI之cookie设置
一.测试背景: 1)接口测试需要完成注册-->登录-->充值,使用soapui构建好测试用例.设置断言后,运行结果如下: 2)recharge接口运行失败,继续查看该接口具体发送的请求及返 ...
- lvs,nginx反向代理,虚拟主机
LVS NAT 拓扑 client | | LVS | | ------------------- | | | RS1 RS2 RS3 地址规划如下 机器名称 ip配置 ip配置 备注信息 LVS 1 ...
- 学习poisson.c
static char help[] = "A structured-grid Poisson problem with DMDA+KSP.\n\n"; #include < ...