go語言中帶緩沖區的channel的使用


一.本文主要針對以下問題:

1.帶緩沖區的channel

2.在兩個goroutine之間進行消息的交互

3.偶爾會有消息到達,有時又阻塞於沒有消息到達

4.兩個goroutine一直存在

設計思路,首先要保證channel構造完成前,發送和接收的消息都沒有使用channel,不然會導致channel阻塞

二.下面是錯誤的代碼:

1.發送端:

package ioproc

import (
   "fmt"
   "time"
)

var ChT = make([]chan int,4)
func Send(){
   fmt.Println("Send entry.....")

   for i:=0;i<4;i++{
      go func(i int){
         var temp = 0
         ChT[i] = make(chan int,5000)

         for {
            time.Sleep(time.Millisecond*1000)
            temp++
            ChT[i] <- temp
            fmt.Println("Send temp ok,",i,"Send")
         }

      }(i)
   }

}

  


代碼解釋:發送函數部分,1.聲明了一個全局的channel數組變量,ChT[]
            2.定義send函數:使用for循環,在每個for循環開啟一個goroutine,並將ChT[i]進行make為緩沖區大小是5000的channel
            3.一直執行for循環,往ChT[i]中進行添加數據

2.接收端
package utility

import (
   "SIPLBS/ioproc"
   "fmt"
)

func Recv(){
   for{
      select{
      case tNumber := <- ioproc.ChT[0]:
         fmt.Println("the ",0,"routine is ",tNumber)

      case tNumber := <- ioproc.ChT[1]:
         fmt.Println("the ",1,"routine is ",tNumber)
      case tNumber := <- ioproc.ChT[2]:
         fmt.Println("the ",2,"routine is ",tNumber)

      case tNumber := <- ioproc.ChT[3]:
         fmt.Println("the ",3,"routine is ",tNumber)
      }
   }
}

  


代碼解釋:接收函數部分:1.定義函數,並在函數中一直for循環,通過select一直接收ChT[i]中的數據

3.main包函數:
func init(){
   fmt.Println("init entry......")

   go ioproc2.Send()

   go ioproc.Recv()
}

 

4.打印結果:

init entry......
Send entry.....
sendsip begin...
Send temp ok, 1 Send
Send temp ok, 0 Send
Send temp ok, 3 Send
Send temp ok, 2 Send
Send temp ok, 0 Send
Send temp ok, 1 Send
Send temp ok, 3 Send
Send temp ok, 2 Send
Send temp ok, 2 Send

可以看到一直有消息往channel中發送,但是recv的GoRoutine一直未收到消息


三.修改之后的代碼

1.發送端
import (
	"fmt"
	"time"
)

var ChT = make([]chan int,4)

func init(){
	fmt.Println("init entry......")

	for i := 0 ; i < 4; i++{
		ChT[i] = make(chan int,5000)
	}
}

func Send(){
	fmt.Println("Send entry.....")

	for i:=0;i<4;i++{
		go func(i int){
			var temp = 0
			for {
				time.Sleep(time.Millisecond*1000)
				temp++
				ChT[i] <- temp
				fmt.Println("Send temp ok,",i,"Send")
			}

		}(i)
	}
}

2.接收端

package utility

import (
	"SIPLBS/ioproc"
	"fmt"
)

func Recv(){
	for{
		select{
		case tNumber := <- ioproc.ChT[0]:
			fmt.Println("the ",0,"routine is ",tNumber)

		case tNumber := <- ioproc.ChT[1]:
			fmt.Println("the ",1,"routine is ",tNumber)
		case tNumber := <- ioproc.ChT[2]:
			fmt.Println("the ",2,"routine is ",tNumber)

		case tNumber := <- ioproc.ChT[3]:
			fmt.Println("the ",3,"routine is ",tNumber)
		}
	}
}

  3.main包程序

func main() {

	go ioproc2.Send()

	go utility.Recv()
}

 代碼解釋:目的是將channel放在send和recv兩個goroutine啟動之前已經准備好,所以將channel的初始化部分放到了先於main執行的init函數中,然后在main函數中起send和recv協程。

4.結果打印:

init entry......
Send entry.....
Send temp ok, 1 Send
Send temp ok, 3 Send
Send temp ok, 2 Send
the 3 routine is 1
the 1 routine is 1
the 2 routine is 1
Send temp ok, 0 Send
the 0 routine is 1

 

還可以改進代碼,將三個函數都封裝到一個類中進行處理,在類進行初始化的時候,可以把channel進行初始化,

然后開啟goroutine,這樣就可以確保發送和接收的goroutine是在channel准備好的情況下進行執行的。

 





 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM