<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] ## 概述 - 不管是使用 **sync.WaitGroup**,還是 **context.Background** 都可以防止協程泄露 - 都是通過 chan 的關閉來觸發退出 ## 實例 ### sync.WaitGroup 控制一個結構體退出 <details> <summary>main.go</summary> ``` package main import ( "fmt" "os" "os/signal" "sync" "time" ) type server struct { quit chan struct{} isrun bool wait sync.WaitGroup } func newServer() *server { return &server{ quit:make(chan struct{}), wait: sync.WaitGroup{}, isrun:true, } } func (s *server) close(){ close(s.quit) s.wait.Wait() } func (s *server) task(){ s.wait.Add(1) defer s.wait.Done() for { select { case <-s.quit: // 退出協程 fmt.Printf("%+v\n", "stop") return default: } fmt.Printf("%+v\n", "task") go s.subtask() time.Sleep(1*time.Second) } } func (s *server) subtask() { s.wait.Add(1) defer s.wait.Done() for { select { case <-s.quit: // 退出協程 fmt.Printf("%+v\n", "sub——stop") return default: } fmt.Printf("%+v\n", "subtask") time.Sleep(1*time.Second) } } func main() { s := newServer() defer s.close() go s.task() sig:=make(chan os.Signal) signal.Notify(sig,os.Interrupt) <-sig } ``` </details> <br/> 輸出 ``` subtask subtask subtask subtask sub——stop sub——stop stop sub——stop sub——stop sub——stop ``` ### sync.WaitGroup 控制兩個結構體退出 第一個結構體也可以采用 chan 的方式去控制退出 <details> <summary>main.go</summary> ``` package main import ( "fmt" "os" "os/signal" "sync" "time" ) type Big struct { wait sync.WaitGroup } func (b *Big) run() { for i := 0; i < 10; i++ { b.wait.Add(1) go func(index int) { defer b.wait.Done() s := small{} s.Run(index) }(i) } } func (b *Big) Close() { fmt.Println("ready quit ..") b.wait.Wait() fmt.Println("quit ...") } type small struct { } func (s *small) Run(j int) { for i := 0; i < 5; i++ { fmt.Printf("%+v-%v\n", j, i) time.Sleep(1 * time.Second) } } func main() { var b Big b.run() defer b.Close() s := make(chan os.Signal) signal.Notify(s, os.Kill, os.Interrupt) <-s } ``` </details> <br/> ### context 控制退出 實例可參考 https://github.com/9b9387/zero <details> <summary>main.go</summary> ``` package main import ( "context" "fmt" "os" "os/signal" "time" ) type Big struct { quitBig chan struct{} } func NewBig() *Big{ return &Big{ quitBig: make(chan struct{}), } } func (b *Big)Run(){ ctx := context.Background() ctx,cancal:=context.WithCancel(ctx) defer cancal() for i:=0; i<5; i++ { go b.handle(ctx,i) } for { select { case <-b.quitBig: // 通過觸發chan來觸發 cancal() return } } } func (b *Big) handle(ctx context.Context,i int) { sm:=NewSmall() go sm.Write(ctx,i) go sm.Read(ctx) select { case <-sm.quitSmall: return } } func (b *Big)Close(){ close(b.quitBig) } //========================== // 子程序 //========================== type Small struct { quitSmall chan struct{} msg chan string } func NewSmall()*Small{ return &Small{ quitSmall: make(chan struct{}), msg: make(chan string,10), } } func (s *Small) Write(ctx context.Context,o int){ defer s.Close() for i:=0; i<5; i++ { // 每次執行判斷ctx 是否斷掉 select { case <-ctx.Done(): return default: } s.msg <- fmt.Sprintf("%v-%v", i, o) time.Sleep(1 * time.Second) } } func (s *Small) Read(ctx context.Context){ for{ select { case <-ctx.Done(): return case msg:=<-s.msg: fmt.Printf("%+v\n", msg) case <-s.quitSmall: return } } } func (s *Small) Close() { close(s.quitSmall) } func main() { big := NewBig() go big.Run() defer big.Close() s:=make(chan os.Signal,1) signal.Notify(s,os.Kill,os.Interrupt) <-s } ``` </details> <br/>
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看