searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Go Context学习

2023-06-01 09:52:26
22
0

Context(上下文)一般理解为程序单元的一个运行状态、现场、快照。其中上下是指存在上下层的传递,上会把内容传递给下,程序单元则指的是 Goroutine。即:在一组goroutine之间传递取消信号、共享的值、超时时间等等。

 

context 的函数、接口、结构体

 

Context 接口定义如下:

type Context interface {
    Deadline() (deadline time.Time, ok bool)
    Done() <-chan struct{}
    Err() error
    Value(key interface{}) interface{}
}

其中:

  • Deadline 方法返回当前 Context 被取消的时间,也就是完成工作的截止时间(deadline);
  • Done 方法返回一个 Channel,这个 Channel 会在当前工作完成或者上下文被取消之后关闭,多次调用 Done 方法会返回同一个Channel;
  • Err 方法会返回当前 Context 结束的原因,它只会在 Done 返回的 Channel 被关闭时才会返回非空的值:
    • 如果当前 Context 被取消就会返回 Canceled 错误;
    • 如果当前 Context 超时就会返回 DeadlineExceeded 错误;
  • Value 方法会从 Context 中返回键对应的值,对于同一个上下文来说,多次调用 Value 并传入相同的 Key 会返回相同的结果,该方法仅用于传递跨 API 和进程间跟请求域的数据。

连续多次调用同一个方法,得到的结果都是相同的。

常用方法:context.Backgroud()、context.TODO()

func Background() Context {
	return background
}

func TODO() Context {
	return todo
}
  • context.Background 是上下文的默认值(根Context),所有其他的上下文都应该从它衍生出来;
  • context.TODO 应该仅在不确定应该使用哪种上下文时使用;

With系列函数:

func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc)
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
func WithValue(parent Context, key, val interface{}) Context

其中:

  • context.WithCancel 函数能够从 context.Context 中衍生出一个新的子上下文并返回用于取消该上下文的函数。一旦我们执行返回的取消函数,当前上下文以及它的子上下文都会被取消,所有的 Goroutine 都会同步收到这一取消信号。
  • context.WithDeadline 会返回父上下文的副本,并将 deadline 调整为不迟于 d。当时间超过了截止日期后会调用 context.timerCtx.cancel 同步取消信号,从而实现定时取消。
  • context.WithTimeout 也能通过创建可以被取消的计时器上下文 context.timerCtx,实现定时取消
  • context.WithValue 能从父上下文中创建一个子上下文,用于传递goroutine之间需要共享的数据

官方的几点Context使用建议:

  1. 不要将 Context 塞到结构体里。直接将 Context 类型作为函数的第一参数,而且一般都命名为 ctx。
  2. 不要向函数传入一个 nil 的 context,如果你实在不知道传什么,标准库给你准备好了一个 context:todo。
  3. 不要把本应该作为函数参数的类型塞到 context 中,context 存储的应该是一些共同的数据。例如:登陆的 session、cookie 等。
  4. 同一个 context 可能会被传递到多个 goroutine,别担心,context 是并发安全的。
  5. Go 语言中的 context.Context的主要作用还是在多个 Goroutine 组成的树中同步取消信号以减少对资源的消耗和占用。建议尽量不要传值:

——在一个处理过程中,有若干子函数、子协程。各种不同的地方会向 context 里塞入各种不同的 k-v 对,最后在某个地方使用。你根本就不知道什么时候什么地方传了什么值,以及这些值会不会被“覆盖”。

0条评论
0 / 1000
霍欣莉
4文章数
0粉丝数
霍欣莉
4 文章 | 0 粉丝
霍欣莉
4文章数
0粉丝数
霍欣莉
4 文章 | 0 粉丝
原创

Go Context学习

2023-06-01 09:52:26
22
0

Context(上下文)一般理解为程序单元的一个运行状态、现场、快照。其中上下是指存在上下层的传递,上会把内容传递给下,程序单元则指的是 Goroutine。即:在一组goroutine之间传递取消信号、共享的值、超时时间等等。

 

context 的函数、接口、结构体

 

Context 接口定义如下:

type Context interface {
    Deadline() (deadline time.Time, ok bool)
    Done() <-chan struct{}
    Err() error
    Value(key interface{}) interface{}
}

其中:

  • Deadline 方法返回当前 Context 被取消的时间,也就是完成工作的截止时间(deadline);
  • Done 方法返回一个 Channel,这个 Channel 会在当前工作完成或者上下文被取消之后关闭,多次调用 Done 方法会返回同一个Channel;
  • Err 方法会返回当前 Context 结束的原因,它只会在 Done 返回的 Channel 被关闭时才会返回非空的值:
    • 如果当前 Context 被取消就会返回 Canceled 错误;
    • 如果当前 Context 超时就会返回 DeadlineExceeded 错误;
  • Value 方法会从 Context 中返回键对应的值,对于同一个上下文来说,多次调用 Value 并传入相同的 Key 会返回相同的结果,该方法仅用于传递跨 API 和进程间跟请求域的数据。

连续多次调用同一个方法,得到的结果都是相同的。

常用方法:context.Backgroud()、context.TODO()

func Background() Context {
	return background
}

func TODO() Context {
	return todo
}
  • context.Background 是上下文的默认值(根Context),所有其他的上下文都应该从它衍生出来;
  • context.TODO 应该仅在不确定应该使用哪种上下文时使用;

With系列函数:

func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc)
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
func WithValue(parent Context, key, val interface{}) Context

其中:

  • context.WithCancel 函数能够从 context.Context 中衍生出一个新的子上下文并返回用于取消该上下文的函数。一旦我们执行返回的取消函数,当前上下文以及它的子上下文都会被取消,所有的 Goroutine 都会同步收到这一取消信号。
  • context.WithDeadline 会返回父上下文的副本,并将 deadline 调整为不迟于 d。当时间超过了截止日期后会调用 context.timerCtx.cancel 同步取消信号,从而实现定时取消。
  • context.WithTimeout 也能通过创建可以被取消的计时器上下文 context.timerCtx,实现定时取消
  • context.WithValue 能从父上下文中创建一个子上下文,用于传递goroutine之间需要共享的数据

官方的几点Context使用建议:

  1. 不要将 Context 塞到结构体里。直接将 Context 类型作为函数的第一参数,而且一般都命名为 ctx。
  2. 不要向函数传入一个 nil 的 context,如果你实在不知道传什么,标准库给你准备好了一个 context:todo。
  3. 不要把本应该作为函数参数的类型塞到 context 中,context 存储的应该是一些共同的数据。例如:登陆的 session、cookie 等。
  4. 同一个 context 可能会被传递到多个 goroutine,别担心,context 是并发安全的。
  5. Go 语言中的 context.Context的主要作用还是在多个 Goroutine 组成的树中同步取消信号以减少对资源的消耗和占用。建议尽量不要传值:

——在一个处理过程中,有若干子函数、子协程。各种不同的地方会向 context 里塞入各种不同的 k-v 对,最后在某个地方使用。你根本就不知道什么时候什么地方传了什么值,以及这些值会不会被“覆盖”。

文章来自个人专栏
go语言
1 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0