記事のコード部分は、ダイビング・ツー・gosync・ワークショップベースのコード
NewTimer Golangメソッド呼び出しの後、タイマーは、配置された最小のスタックを生成する背景ゴルーチンスタックをスキャンし、タイマーコールバックチャネル(次のコードC:=(チャン時間、1)を作る)の時間が書き込まれます
// NewTimerがお送りします新しいタイマーを作成 、少なくとも持続時間Dの後にそのチャンネルに//現在の時間を。 FUNC NewTimer(D期間)*タイマ{ C:=作る(チャン時間、1) T:=&タイマ{ C:C、 R:runtimeTimer { (D)、 F:SENDTIME、 引数:C、 }、 } startTimer(&t.r) 戻りT }
タイマーをgolangの停止方法、タイマーは、群衆の中から除去するためにのみ責任がある、チャネルの上に近い(なぜ近いチャネル?ただ、現在のタイムアウトを参照するには、クラッシュしない簡単な処理するための基礎となるコードについては責任を負いません。実際には、公式にはgolangです正しく)チャネルのタイムアウトを処理するので、いくつかのピットを買う行って。
ない場合は、次のコードは、タイムアウトが書き込まれた後wrongResetAfterFired(..)はチャネルを記載請求ピット及び処理方法を示す、アクティブ正しく受信、タイマーリセットはまだからの最後のチャネルを得るにつながりますチャネルデータ。
wrongStopMore(...)は、チャネルが書かれていない場合ことを示しており、デッドロックにつながる待ち時間に直接行きません
以下のための主要なパッケージ変更 のインポート( 「FMT」 「」ログ 「時間」 ) 、タイマーに// [JZ]は、より重要な点はnewtimer後、タイマーは最小ヒープに配置されるということですされ、その後、コールバックによるスキャンするゴルーチンが、そこにありますチャネル書き込み //停止は原子炉から取り出され、タイマーのための唯一の責任があり、チャネル使用を閉じるための責任を負いません FUNCメイン(){ log.Println(「✔︎resetBeforeFired」) resetBeforeFired() fmt.Println() log.Println(「✘wrongResetAfterFired」) wrongResetAfterFired() fmt.Println() log.Println( "✔︎correctResetAfterFired") correctResetAfterFired() fmt.Println() log.Println( "STOP✔︎n回") stopMore() fmt.Println() log.Println(「✘ 「n回が、ドレインと停止) wrongStopMore() fmt.Println() T: = <-timer.C log.Println( "多すぎる✘受信") wrongReceiveMore() } FUNC resetBeforeFired(){ タイマー:time.NewTimer =(5 * time.Second。) B:= Timer.stop() log.Printf(「STOP:%T 」、B) Timer.reset(* time.Second 1) T:= <-timer.C log.Printf( "%S AT"は焼成、t.String()) } FUNC wrongResetAfterFired(){ タイマ=時間。 (5 * time.Millisecond)NewTimer time.sleep(time.Second)//スリープLS上記タイマが満了確保、チャネルが書かれている Bを:= Timer.stop() log.Printf( "STOP:%T"、 B) TT:Timer.reset =(10 * time.Second) fmt.Println(TT) チャネルの//この時点で最初のタイムアウトタイマーで取得(5ミリ秒)値 で焼成log.Printf(」 %s」は、T。文字列()) } correctResetAfterFired FUNC(){ タイマー:time.NewTimer =(5 * time.Millisecond) time.sleep(time.Second) B:= Timer.stop() log.Printf( "STOP:%T"、B) //もしディスカバリー時間が書込みチャネルに満了すると、読み出しチャネルの前に、後に値をリセットするように、読んでください停止 !IF {B = <-timer.C:T fmt.Println(t.String ()) } log.Printf( "RESET") Timer.reset(10 * time.Second) T:= <-timer.C log.Printf( "%S ATが発射"、t.String()) } FUNC wrongReceiveMore (){ タイマー:time.NewTimer =(5 * time.Millisecond。) T:= <-timer.C FUNC stopMore(){ log.Printfは(「%で焼成S」、T。文字列()) T = <-timer.C log.Printf( "%で再びSを受信" t.String()) } タイマー:(5 * time.Millisecond)time.NewTimer = B = Timer.stop() log.Printf( "STOPた:%T" 、B) time.sleep(time.Second) B = Timer.stop() log.Printf( "詳細STOP:%T"、Bは) } / * newtimer後、タイマーは最小ヒープで、次いでゴルーチンに配置されます、スキャンによるコールバックチャネル書き込み 停止タイマをスタックからのみ責任が除去され、チャネルを閉じるための責任を負いません * / FUNC wrongStopMore(){ タイマー:time.NewTimer =(5 * time.Millisecond。) B:= Timer.stop () log.Printf( "STOP:%T"、B) time.sleep(time.Second) B = Timer.stop() !B {// IFは、B && LEN(timer.C場合:!解決考えることができます)> 0 //理由で問題である理由は、その最初の時間停止呼び出しのために、タイマーが切れる前にそれが起こった、タイマーがこの時点でスタックから削除されていますが、タイムアウトタイマーを持っていないので、チャンネルを送信する必要 この時点で//あなたはtimer.Cの結果を待つ必要はありませんでしょう //たとえば、あなたの睡眠の1秒前に最初timer.Stopは、タイマーのタイムアウトを聞かせて、チャネルが書き込まれます、その後、タイマー.C待っている問題はありません <-timer.C } time.sleep(* 1時間。 SECOND) log.Printf( "詳細STOP:%T"、B) }