- チャネルとヌル値
- 片道チャンネル
- メインOSスレッドでの実行
- ブロッキング操作の削除
チャネルとヌル値
チャネルは、非同期開発のためのツールです。 ただし、多くの場合、チャネルで何を転送するかは重要ではありません。転送の事実のみが重要です。 時々見つかる
完了:= make ( chan bool )
/// [...]
完了< -true
boolのサイズはプラットフォームによって異なります。はい、通常、サイズについて心配する必要がある場合はそうではありません。 しかし、まだ何も送信しない、または何も送信しない方法があります(さらに正確には、空の構造について話している)。
done := make ( chan struct { } )
// [...]
完了< -struct { } { }
それだけです。
片道チャンネル
もう1つ明確に強調したい点があります。 例:
func main ( ) {
done := make ( chan struct { } )
go func ( ) {
//もの
done < -struct { } { } //完了前に通知する
} ( )
< -done //ゴルーチンの完了を待機
}
それは簡単です- ゴルーチンで 行われるのは記録のためだけに必要です。 原則として、 ゴルーチンではそれを読み取ることができます( 完了チャネルから値を取得します)。 トラブルを避けるために、コードが混乱している場合、パラメーターが役立ちます。 goroutineに渡される関数のパラメーター。 今そう
func main ( ) {これで、このようなチャネルを送信すると、書き込み専用チャネルに変換されます。 ただし、以下では、チャネルは双方向のままです。 原則として、チャネルは引数を渡さずに一方向に変換できます。
done := make ( chan struct { } )
go func ( done chan < -struct { } ) {
//もの
done < -struct { } { } //完了前に通知する
} (完了)
< -done //ゴルーチンの完了を待機
}
done := make ( chan struct { } )頻繁に必要に応じて、これらすべてを行う関数を作成できます。 これがplay.golang.orgの例です 。 これにより、コンパイル段階でいくつかのエラーをキャッチできます。
writingChan := ( chan < -struct { } ) ( done ) //最初の括弧は重要ではありません
readingChan := ( <- chan struct { } ) ( done ) //最初の括弧が必要です
メインOSスレッドでの実行
たとえば、OpenGL、libSDL、Cocoaなどのライブラリは、プロセスデータ構造にスレッドローカルストレージを使用します。 つまり、メインOSスレッドで実行する必要があります。それ以外の場合はエラーになります。
runtime.LockOSThread()
関数を使用すると、現在のゴルーチンをOSの現在のスレッドに固定できます。 初期化中に(
init
関数で)呼び出すと、これがメインOSスレッド(メインOSスレッド)になります。 同時に、他のゴルーチンは並列OSスレッドで静かに実行できます。
別のスレッドで計算を行うには(この場合は、別のOSスレッドにあるという事実ではなく、ゴルーチンについて話します)、関数をメインのスレッドに単純に転送するだけで十分です。 以上です。
シーツ
play.golang.orgで
パッケージ メイン
インポート (
「fmt」
「ランタイム」
)
func init ( ) {
ランタイム。 LockOSThread ( ) //現在のゴルーチンを現在のスレッドに固定する
}
func main ( ) {
/ *
コミュニケーション
* /
done := make ( chan struct { } ) // <-停止して終了
stuff := make ( chan func ( ) ) // <-メインスレッドに関数を送信
/ *
2番目のスレッドを作成します(この場合、2番目のゴルーチンですが、問題ではありません)
そして、最初に「ジョブ」の送信を開始します
* /
go func ( done chan < -struct { } 、stuff chan < -func ( ) ) { //並列操作
stuff < -func ( ) { //最初に行った
fmt。 Println ( "1" )
}
stuff < -func ( ) { // 2番目の
fmt。 Println ( "2" )
}
stuff < -func ( ) { // 3番目に行った
fmt。 Println ( "3" )
}
完了< -struct { } { }
} (完了、スタッフ)
ループ:
{
{を選択
case do := < -stuff : //「作業」を取得
do ( ) //および実行
ケース <-完了:
ブレークループ
}
}
}
ブロッキング操作の削除
IO操作のブロックはより一般的ですが、同様に無効にされます。
シーツ
複数のゴルーチンが1人の「ライター」にメッセージを送信した場合でも、ブロックされます。 この場合、バッファのあるチャネルが役立ちます。 スライスが参照タイプである場合、ポインターのみがチャネルを介して送信されます。
play.golang.orgで
パッケージ メイン
「os」を インポート
func main ( ) {
/ *
コミュニケーション
* /
stop := make ( chan struct { } ) //「書き込み」ゴルーチンを停止するために必要
done := make ( chan struct { } ) //完了するのを待つ
write := make ( chan [ ] byte ) //書き込み用データ
/ *
IO操作用の並列スレッド
* /
go func ( write < -chan [ ] byte 、stop < -chan struct { } 、done chan < -struct { } ) {
ループ:
{
{を選択
case msg := < -write : //書き込みメッセージを受信
os。 標準出力 。 書き込み ( msg ) //非同期書き込み
ケース <-停止:
ブレークループ
}
}
完了< -struct { } { }
} (書き込み、停止、完了)
write <- [ ] byte ( "Hello" ) //メッセージを送信
write <- [ ] byte ( "World! \ n " ) //書き込み
停止< -struct { } { } //停止
< -done //完了を待つ
}