Goのchannelの一般的な使い方

5346 ワード

goキーワードは1つのgoroutine(協程))を開いてタスク処理を行うことができ、複数のタスク間で通信が必要な場合はchannelを使用する必要があります.
func testSimple(){
	intChan := make(chan int)

	go func() {
		intChan 

上記の簡単な例は、新しくオープンしたgoroutineがintChanに1の値を送信すると、メインスレッドのintChanでこの値の情報が受信されます.
channelタイプ:バッファなしおよびバッファタイプ
channelにはバッファなしの2つの形式があり、1つのスレッドがこのchannelにメッセージを送信すると、現在のスレッドがブロックされ、他のスレッドがこのchannelのメッセージを受信することを知っています.バッファなしの形式は次のとおりです.
intChan := make(chan int)

バッファ付きchannelは、バッファ付きメッセージの数を指定できます.メッセージの数が指定値より小さい場合、ブロックは発生しません.それを超えるとブロックされません.他のスレッドがchannel処理を受信するのを待つ必要があります.バッファ付きの形式は以下の通りです.
//3     
intChan := make(chan int, 3)

struct構造データの転送
channelはint,stringなどの基本的なタイプのデータを伝送することができ、structデータも伝送することができる.

type Person struct {
	Name    string
	Age     uint8
	Address Addr
}

type Addr struct {
	city     string
	district string
}

/*
  channel     Struct  
 */
func testTranslateStruct() {
	personChan := make(chan Person, 1)

	person := Person{"xiaoming", 10, Addr{"shenzhen", "longgang"}}
	personChan 

ここでは,チャネルを介してカスタムPersonオブジェクトを転送し,一方の端がデータを修正し,他方の端のデータに影響を及ぼさない,すなわちチャネルを介して転送されたデータは独立していることがわかる.
チャンネルを閉じる
channelは閉じることができ、例えば書かれたセグメントがchannelを閉じると、読み取りの一端が読み取られたときに読み取り失敗を検出することができる.
/*
    channel
 */
func testClose() {
	ch := make(chan int, 5)
	sign := make(chan int, 2)

	go func() {
		for i := 1; i <= 5; i++ {
			ch 

複数のchannelの出力をマージ
複数のchannelのデータを1つのchannelに統合して出力し、メッセージキューを形成することができます.
/**
      channel       channel
 */
func testMergeInput() {
	input1 := make(chan int)
	input2 := make(chan int)
	output := make(chan int)

	go func(in1, in2 

チャネルによる脱退の通知
終了するためのchannel、例えばquitを定義し、タスクを継続的に実行するスレッドはselectを通じてquitの読み取りを傍受し、quit内のメッセージを読み取ると、現在のタスクスレッドを終了します.ここでは、メインスレッドがタスクスレッドの終了を通知します.
/*
  channel           
 */
func testQuit() {
	g := make(chan int)
	quit := make(chan bool)

	go func() {
		for {
			select {
			case v := 

生産者消費者問題
チャネルによって生産者消費者モデルを比較的容易に実現することができ、ここでは生産者スレッド、消費者スレッドを開き、生産者スレッドはチャネルにメッセージを送信し、同時にブロックし、消費者スレッドはチャネルのメッセージをポーリングして取得し、処理し、ブロックし、このとき生産者スレッドは後続の論理を起動し、このようにして簡単な生産者消費者モデルが形成された.同時に、生産者はすべてのメッセージの送信を完了した後、quitというchannelを通じて消費者スレッドの終了を通知することができ、消費者スレッドの終了時に、メインスレッドの終了を通知し、プログラム全体の終了を完了することができる.
/**
        
 */
func testPCB() {
	fmt.Println("test PCB")

	intchan := make(chan int)
	quitChan := make(chan bool)
	quitChan2 := make(chan bool)

	value := 0

	go func() {
		for i := 0; i < 3; i++ {

			value = value + 1
			intchan 

しゅつりょくちくじもんだい
/*
       1,2,     2,1,     2,       
 */
func testSequnse() {
	ch := make(chan int)

	go func() {
		v := 

上の出力結果は何ですか?実行してみると、1,2かもしれないし、2,1かもしれないし、2かもしれないし、順序が一定ではないのに、なぜそうなるのか、これは2つの異なるスレッドなので、独立して実行されていると思います.v:=
channelのタイムアウト処理
timeによりchannelのタイムアウト処理を実現することができ、1つのchannelが一定時間を超えてメッセージが来ない場合、タイムアウト通知処理を得ることができ、現在のスレッドをブロックし続けることを防止することができる.
/*
  channel    ,       
 */
func testTimeout() {
	g := make(chan int)
	quit := make(chan bool)

	go func() {
		for {
			select {
			case v := 

channelの入出力タイプ指定
channelは、入力型か出力型かを指定し、入力型かを指定すると、メッセージを出力することはできません.そうしないと、エラーコンパイルが通過しません.同じように、出力型はメッセージ入力を受け入れることができません.これにより、コードを書くときに、手の誤記入力がタイプを入力してプログラムエラーを引き起こす問題を防ぐことができます.入力出力タイプを指定してメソッドパラメータを設定すると、現在のメソッドでのみ入力出力制限が行われます.以下を参照してください.
/*
  channel         ,            ,     ,             
 */
func testInAndOutChan() {
	ch := make(chan int)
	quit := make(chan bool)

	//    chan      :inChan chan

channelによる同時数量制御の実現
バッファ付きchannelを設定することで最大同時数を実現し、最大同時数はバッファ数であり、タスク開始時にlimitというchannelにメッセージを送信し、タスク実行完了後にこのlimitからメッセージを読み出すことで、limitのバッファ数に達するとlimitが新しいスレッドを作成することを保証することができる.あるスレッドがタスクを完了したことを知った後、limitからデータを読み込むと、最大同時数がバッファ数に制御されることが保証されます.
/*
    channel        ,     
 */
func testMaxNumControl()  {
	maxNum := 3
	limit := make(chan bool, maxNum)
	quit := make(chan bool)

	for i:=0; i<100; i++{
		fmt.Println("start worker : ", i)

		limit 

割り込み信号を傍受するチャンネル
signal信号のchannelを作成し、signalを通過することができる.見てみろInterruptという割り込み信号は、osが受信まで実行される.Interruptという割り込み信号は、例えばCtrl+C割り込みプログラムを押すとメインプログラムが終了します.もちろん、osなどの他の信号を傍受することもできる.Killなど./*割り込み信号を傍受するchannel*/func testSignal(){quit:=make(chan os.Signal)signal.Notify(quit,os.Interrupt)
go func() {
	time.Sleep(time.Second * 2)

	number := 0;
	for{
		number++
		println("number : ", number)
		time.Sleep(time.Second)
	}
}()

fmt.Println(" Ctrl+C     ")

}
channelは同期制御を実現し,生産者消費者モデル
複数のスレッドを開いてお金を稼ぐ操作を行い、remainMoneyという残りの金額変数を共有し、生産者消費者モデルを実現する.
//      ,     
var lockChan = make(chan int, 1)
var remainMoney = 1000
func testSynchronize()  {
	quit := make(chan bool, 2)

	go func() {
		for i:=0; i<10; i++{
			money := (rand.Intn(12) + 1) * 100
			go testSynchronize_expense(money)

			time.Sleep(time.Millisecond * time.Duration(rand.Intn(500)))
		}

		quit = money){
		srcRemainMoney := remainMoney
		remainMoney -= money
		fmt.Printf("   %d,   %d,  %d
", srcRemainMoney, money, remainMoney) }else{ fmt.Printf(" %d , %d
", money, remainMoney) }
  • pinery.cn