The traditional way
In the beginning of the school go, never used Context package, then exit Ctrip way to have so few
Using the notification message transmitted chan carrying this general only suitable for single goroutine
func exit01() {
done := make(chan bool)
go func() {
for {
select {
case <-done:
fmt.Println("退出携程")
return
default:
fmt.Println("监控中...")
time.Sleep(1 * time.Second)
}
}
}()
time.Sleep(3 * time.Second)
done <- true
time.Sleep(5 * time.Second)
fmt.Println("程序退出")
}
Use closed chan way to notify multiple goroutine exit
func exit02() {
done :=make(chan bool)
go func() {
for{
select {
case <-done:
fmt.Println("退出携程01")
return
default:
fmt.Println("监控01...")
time.Sleep(1*time.Second)
}
}
}()
go func() {
for res :=range done{ //没有消息阻塞状态,chan关闭 for 循环结束
fmt.Println(res)
}
fmt.Println("退出监控03")
}()
go func() {
for{
select {
case <-done:
fmt.Println("退出携程02")
return
default:
fmt.Println("监控02...")
time.Sleep(1*time.Second)
}
}
}()
time.Sleep(3*time.Second)
close(done)
time.Sleep(5*time.Second)
fmt.Println("退出程序")
}
Acquaintance Context package
A manual control for the exit or end goroutine
Two ways to get context context
ctx := context.Background() //这只能用于高等级(在 main 或顶级请求处理中)。这能用于派生我们稍后谈及的其他 context
ctx := context.TODO() // 也只能用于高等级或当您不确定使用什么 context,或函数以后会更新以便接收一个 context
Their underlying achieve exactly the same, the difference is that static analysis tools can use it to verify context is correct pass,
this is an important detail, because the static analysis tools can help identify potential errors early, and can connect to CI / CD pipes
var (
background = new(emptyCtx)
todo = new(emptyCtx)
)
Use context.WithTimeout, take the initiative to call the cancel () method, you can exit before time expires goroutine
func exit03() {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
go func() {
for{
select {
case <-ctx.Done():
fmt.Println("退出携程")
return
default:
fmt.Println("请求中..")
time.Sleep(1*time.Second)
}
}
}()
time.Sleep(5*time.Second)
//cancel() //也可以手动调用 cancel()方法退出
//time.Sleep(2*time.Second)
fmt.Println("程序退出")
}
Use context.WithCanel () method, according to the external conditions of manual call cancel () method to exit
only create its function can be called to cancel functions to cancel this context. If you prefer, you can cancel the transfer function, however, is strongly discouraged.
This may result in the caller did not realize cancel cancel function of downstream impacts context. There may be other context from this, and
this may cause the program to run in unexpected ways. In short, never cancel the transfer function
func exit04() {
ctx, cancel := context.WithCancel(context.Background())
go func() {
for{
select {
case <-ctx.Done():
fmt.Println("退出携程")
return
default:
fmt.Println("监控01")
time.Sleep(1*time.Second)
}
}
}()
time.Sleep(5*time.Second)
cancel()
time.Sleep(2*time.Second)
fmt.Println("退出程序")
}
Use context.WithDeadLine (), exit at a specified time goroutine
func exit05() {
stringTime := "2019-08-11 09:08:01"
loc, _ := time.LoadLocation("Local")
the_time, _ := time.ParseInLocation("2006-01-02 15:04:05", stringTime, loc)
ctx, _ := context.WithDeadline(context.Background(), the_time)
go func() {
for{
select {
case <-ctx.Done():
fmt.Println("退出 goroutine")
return
default:
fmt.Println("监控...")
time.Sleep(1*time.Second)
}
}
}()
time.Sleep(60*time.Second)
fmt.Println("程序退出")
}
Use context.WithValue () by value, can be acquired in all of the context tree to the value, if the key is set to cover the same value
does not recommend use of context parameter values passed critical, but is a function of those values to be received signature so made explicit.
func exit06() {
ctx := context.WithValue(context.Background(), "msg", "hello word")
go func(ctx context.Context) {
fmt.Println(ctx.Value("msg"))
}(ctx)
time.Sleep(2*time.Second)
fmt.Println("程序退出")
}
Recommendations constraints
- context.Background applied only at the highest level, as the root of all derived context.
- context.TODO application in uncertain where what you want to use, or after the current function will be updated to use context.
- Cancel suggestive context, these functions may take some time to clean up and exit.
- context.Value should be rarely used, it should not be used to pass optional parameters. This API makes the implicit and can cause errors. Instead, these values should be passed as a parameter.
- Do not stored in the context structure, function transfer them explicitly, preferably as the first parameter.
- Never passed context does not exist. Conversely, if you are not sure what to use, use a ToDo context.
- Context structure no cancellation method, since only a derived function should be canceled before the context of context.
Reference: https://studygolang.com/articles/13866?fr=sidebar