Skip to content

Commit db063f3

Browse files
authored
Merge pull request #302 from devlights/devlights/time-tick-time-newticker-298
Add time_tick_and_ticker.go
2 parents 96b9633 + a7178c6 commit db063f3

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

examples/basic/times/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@
99
|time\_unix\_to\_time.go|time\_unix\_to\_time|time.Unix(sec, nsec) のサンプルです.|
1010
|time\_now.go|time\_now|time.Now() のサンプルです.|
1111
|time\_parse.go|time\_parse|time.Parse() のサンプルです.|
12+
|time\_tick\_and\_ticker.go|time\_tick\_and\_ticker|time.Tick と time.NewTicker の利用シーンの違いについてのサンプルです|
1213

examples/basic/times/examples.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@ func (r *register) Regist(m mappings.ExampleMapping) {
2020
m["time_unix_to_time"] = TimeUnixToTime
2121
m["time_now"] = TimeNow
2222
m["time_parse"] = TimeParse
23+
m["time_tick_and_ticker"] = TickAndTicker
2324
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package times
2+
3+
import (
4+
"time"
5+
6+
"github.com/devlights/gomy/output"
7+
)
8+
9+
// TickAndTicker -- time.Tick と time.NewTicker の利用シーンの違いについてのサンプルです。
10+
func TickAndTicker() error {
11+
// -------------------------------------------------
12+
// time.Tick と time.NewTicker の使い分け
13+
//
14+
// time.Tick は、以下の定義となっている。
15+
// func Tick(d time.Duration) <-chan Time
16+
// 受信専用のチャネルを返しているので、内部で goroutine を
17+
// 起動してチャネル経由で値を返してきている。
18+
// 受信専用のチャネルであるので、このチャネルをユーザ側で
19+
// クローズすることは出来ない。なので、Tickを呼び出した際に
20+
// 生成される goroutine は止まることが無い。
21+
// 止まるタイミングがなく、ずっと動いている goroutine は
22+
// メインゴルーチン以外は goroutine leak していると考える。
23+
//
24+
// なので、time.Tick のドキュメントには以下のように記載されている。
25+
// While Tick is useful for clients that have no need to shut down the Ticker,
26+
// be aware that without a way to shut it down the underlying
27+
// Ticker cannot be recovered by the garbage collector; it "leaks".
28+
//
29+
// time.Tick で生成される goroutine は終了しないので
30+
// アプリケーションの生存期間と同じ時間生存できるタイミングで
31+
// 利用する場合は便利である。
32+
//
33+
// それ以外のケース、例えば 特定の時間枠で処理する goroutineの
34+
// 中で利用したい場合は、time.NewTicker で明示的に time.Ticker を
35+
// 生成して利用するべき。time.Tickerには Stop メソッドが用意されている
36+
// ので、それを呼び出すと内部リソースが開放される。
37+
// (time.Ticker.C のチャネルはクローズされないことに注意)
38+
// -------------------------------------------------
39+
40+
// 一時的な処理時間で動作するゴルーチン
41+
done := func() <-chan struct{} {
42+
done := make(chan struct{})
43+
go func() {
44+
defer close(done)
45+
46+
// このような場合は time.Tick ではなく time.NewTicker を使うべき
47+
ticker := time.NewTicker(500 * time.Millisecond)
48+
timeout := time.After(2 * time.Second)
49+
defer ticker.Stop()
50+
51+
LOOP:
52+
for {
53+
select {
54+
case t := <-ticker.C:
55+
output.Stdoutl("[goroutine] ", t.UTC().Unix())
56+
case <-timeout:
57+
break LOOP
58+
}
59+
}
60+
}()
61+
62+
return done
63+
}()
64+
65+
// ここはメインゴルーチン
66+
// ここで処理が終わるまでインターバルする場合などに利用する場合は
67+
// time.Tick は便利(アプリがそのまま終了するので goroutine leak は問題にならない)
68+
var (
69+
tick <-chan time.Time
70+
timeout = time.After(5 * time.Second)
71+
)
72+
73+
LOOP:
74+
for {
75+
select {
76+
case <-done:
77+
// 非同期処理が終わったのでメインの出力に切り替え
78+
// 再びこのチャネルが select で選択されないように nil を設定しておく
79+
tick = time.Tick(500 * time.Millisecond)
80+
done = nil
81+
82+
output.Stdoutl("[main ]", "goroutine end.")
83+
case t := <-tick:
84+
output.Stdoutl("[main ]", t.UTC().Unix())
85+
case <-timeout:
86+
break LOOP
87+
}
88+
}
89+
90+
return nil
91+
}

0 commit comments

Comments
 (0)