登录
首页 >  Golang >  Go教程

Go 中实现超时控制的方案

来源:脚本之家

时间:2022-12-30 10:41:42 400浏览 收藏

怎么入门Golang编程?需要学习哪些知识点?这是新手们刚接触编程时常见的问题;下面golang学习网就来给大家整理分享一些知识点,希望能够给初学者一些帮助。本篇文章就来介绍《Go 中实现超时控制的方案》,涉及到超时、控制,有需要的可以收藏一下

Timer

在 go 中实现超时控制的方法非常简单,首先第一种方案是 Time.After(d Duration)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
func main() {
    fmt.Println(time.Now())
    x :=
 
<p>output:</p>
<blockquote>
<p>2021-10-27 23:06:04.304596 +0800 CST m=+0.000085653<br>
2021-10-27 23:06:07.306311 +0800 CST m=+3.001711390</p>
</blockquote>
<p style="text-align: center"><img alt="" loading="lazy" src="/uploads/20221230/167236921963ae5443c2555.jpg"></p>
<p><code>time.After()</code> 会返回一个 <code>Channel</code>,该 <code>Channel</code> 会在延时 d 段时间后写入数据。</p>
<p>有了这个特性就可以实现一些异步控制超时的场景:</p>
 
<pre class="brush:plain;">func main() {
    ch := make(chan struct{}, 1)
    go func() {
        fmt.Println("do something...")
        time.Sleep(4*time.Second)
        ch
 
<p>这里假设有一个 <code>goroutine</code> 在跑一个耗时任务,利用 select 有一个 <code>channel</code> 获取到数据便退出的特性,当 <code>goroutine</code> 没有在有限时间内完成任务时,主 <code>goroutine</code> 便会退出,也就达到了超时的目的。</p>
<p>output:</p>
<blockquote>
<p>do something...<br>
timeout</p>
</blockquote>
<p>timer.After 取消,同时 Channel 发出消息,也可以关闭通道等通知方式。</p>
<p>注意 Channel 最好是有大小,防止阻塞 goroutine ,导致泄露。</p>
<h2>Context</h2>
<p>第二种方案是利用 context,go 的 context 功能强大;<br></p>
<p style="text-align: center"><img alt="" loading="lazy" src="/uploads/20221230/167236922063ae544431775.jpg"><br></p>
<p>利用 <code>context.WithTimeout()</code> 方法会返回一个具有超时功能的上下文。</p>
 
<pre class="brush:plain;">ch := make(chan string)
    timeout, cancel := context.WithTimeout(context.Background(), 3*time.Second)
    defer cancel()
    go func() {
        time.Sleep(time.Second * 4)
 
        ch
 
<p>同样的用法,<code>context</code> 的 <code>Done()</code> 函数会返回一个 <code>channel</code>,该 <code>channel</code> 会在当前工作完成或者是上下文取消生效。</p>
<blockquote>
<p>timout context deadline exceeded</p>
</blockquote>
<p>通过 <code>timeout.Err()</code> 也能知道当前 <code>context </code>关闭的原因。</p>
<h2>goroutine 传递 context</h2>
<p>使用 <code>context</code> 还有一个好处是,可以利用其天然在多个 goroutine 中传递的特性,让所有传递了该 context 的 goroutine 同时接收到取消通知,这点在多 go 中应用非常广泛。</p>
 
<pre class="brush:plain;">func main() {
    total := 12
    var num int32
    log.Println("begin")
    ctx, cancelFunc := context.WithTimeout(context.Background(), 3*time.Second)
    for i := 0; i
 
<p>在以上例子中,无论 <code>goroutine</code> 嵌套了多少层,都是可以在 <code>context</code> 取消时获得消息(当然前提是 <code>context</code> 得传递走)</p>
<p>某些特殊情况需要提前取消 context 时,也可以手动调用 <code>cancelFunc()</code> 函数。</p>
<h2>Gin 中的案例</h2>
<p>Gin 提供的 <code>Shutdown(ctx)</code> 函数也充分使用了 <code>context</code>。</p>
 
<pre class="brush:plain;">ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    if err := srv.Shutdown(ctx); err != nil {
        log.Fatal("Server Shutdown:", err)
    }
    log.Println("Server exiting")</pre>
 
<p style="text-align: center"><img alt="" loading="lazy" src="/uploads/20221230/167236922063ae544496804.jpg"></p>
<p>比如以上代码便是超时等待 10s 进行 <code>Gin</code> 的资源释放,实现的原理也和上文的例子相同。</p>
<h2>总结</h2>
<p>因为写 go 的时间不长,所以自己写了一个练手的项目:一个接口压力测试工具。</p>
<p style="text-align: center"><img alt="" loading="lazy" src="/uploads/20221230/167236922163ae544543281.gif"><br><img alt="" loading="lazy" src="/uploads/20221230/167236922163ae5445af1e0.jpg"></p>
<p>其中一个很常见的需求就是压测 N 秒后退出,这里正好就应用到了相关知识点,同样是初学 <code>go</code> 的小伙伴可以参考。</p>
<p><a target="_blank" href="https://www.17golang.com/gourl/?redirect=MDAwMDAwMDAwML57hpSHp6VpkrqbYLx2eayza4KafaOkbLS3zqSBrJvPsa5_0Ia6sWuR4Juaq6t9nq5roGCUgXuytMyero5ko5XFfIfNhNCyr5q5aZrFn2muyGtxYoqRg4PGuruul3qJ07Bme9eala2vkqpxY7F2dqG-a4Fhfo2OsLLNzbCNZJCXvnic25G3y2uR0JOnr4Z9q7KNiWWKjX5pss28oIKbcNDIjHvMnKrQr5rPZZ7Eq32errKFmoqAjmi0p6dojoailb54etyGla6jhdCbZLGGmKCys5yafbOHpLO6s2qNrKKi">https://github.com/crossoverJie/ptg/blob/d0781fcb5551281cf6d90a86b70130149e1525a6/duration.go</a></p>
<p>今天关于《Go 中实现超时控制的方案》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于golang的内容请关注golang学习网公众号!</p></pre></pre></pre>
声明:本文转载于:脚本之家 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>
评论列表