SoFunction
Updated on 2025-03-01

Operation of cross-printing two arrays using Golang's channel

Go's channel provides powerful synchronization function, so how to use channel to cross-print two arrays?

Gray is very simple, just set two channel variables

After printing a value in Array 1, use channel to notify array 2. When printing a value in Array 2, use another channel to notify array 1, synchronization can be achieved.

package main 
import "fmt" 
func main(){
 ch1 :=make(chan int)
 ch2 :=make(chan string)
 str :=[5]string{"a","b","c","d","e"}
 go func() {
  for i:=0;i<5;i++{
   ch1<-i
   (i+1)
   <-ch2
  }
 }()
 
 for _,v :=range str{
  <-ch1
  (v)
  ch2<-v
 }
}

result:

1a2b3c4d5e

Process finished with exit code 0

Supplement: The pit of using golang's channel

Many times, we use buffered channel as communication control function, and some misunderstandings and pitfalls appear.

Misunderstanding 1: There are cache channels in sequence

Execute the following code:

package mainimport (    "time"
    "math/rand")func main(){
    cache:=make(chan int,4)    go func() {        for i:=0;i< 10;i++ {
            cache<-i
        }
    }()    go getCache(cache)    go getCache(cache)    go getCache(cache)
    (3*)
}func getCache(cache <-chan int)  {    for  {        select {        case i:=<-cache:            println(i)
            ((rand.Int31n(100))*)
        }
    }
}

Execute it a few times more and see the results. Not every time can be output sequentially. The cached channel is out of order. Because some students misunderstood this, I will explain it more here.

Both sending and receiving operations for channels may cause related goroutine blockage.

Just imagine that multiple goroutines send data to the same channel and are blocked. If the channel still has extra cache space, the first gated goroutine will be awakened first.

That is to say, the wake-up order here is consistent with the start order of the sending operation, and the same is true for the receiving operation. Whether it is a send or receive operation, the runtime system will only wake up one goroutine at a time.

The out-of-order here means that if the order of multiple goroutines in the cache is correct, because the time point of each goroutine grabs the processor is inconsistent, so the order cannot be guaranteed.

Misunderstanding 2: The size of the channel cache is the concurrency

The following code:

package mainimport ( "fmt"
 "sync"
 "time")var wg = {}func main() {
 (2)
 bf := make(chan string, 64) go insert(bf) go get(bf)
 ()
}func insert(bf chan string) {
 str := "CockroachDB's technology selection is more radical, such as relying on HLC to do transaction timestamps. However, in the Commit Wait phase of Spanner's transaction model, CockroachDB cannot achieve a delay of 10ms; CockroachDB's Commit Wait needs to be specified by the user, but who can tell how many milliseconds the clock error of NTP is? I personally think that in dealing with the problem of clock synchronization across intercontinental computer rooms, there is basically only one way to solve the problem of hardware clock synchronization. HLC cannot solve it. In addition, Cockroach uses gossip to synchronize node information. When the cluster becomes larger, gossip heartbeat will be a very large overhead. Of course, CockroachDB  The advantage of these technical choices is that they are very easy to use. All logic is in a binary and it is used out of the box. This is a very big advantage. "
 for i := 0; i &lt; 10000000; i++ {
  bf &lt;- ("%s%d", str, i)
 }
 ()
}func sprint(s string) {
 (1000 * )
}func get(bf chan string) { for {  go func() {   select {   case str := &lt;-bf:
    sprint(str)   case &lt;-(3 * ):
    ()
   }
  }()
 }
}

Many students think it's defined at first glance

bf := make(chan string, 64)

That is to say, the concurrency of the program is controlled at 64, and the execution will find that the memory is growing.

Because there are more and more goroutines started in the get() function, because every time you read a data from get(), insert() will insert a data into the channel, and the concurrency is no longer 64.

Need to be modified to:

package mainimport ( "fmt"
 "sync"
 "time")var wg = {}func main() {
 (2)
 bf := make(chan string, 64) go insert(bf) //go get(bf)
    for i:=0;i&lt;64;i++ {        go get1(bf)
    }
 ()
}func insert(bf chan string) {
 str := "CockroachDB's technology selection is more radical, such as relying on HLC to do transaction timestamps. However, in the Commit Wait phase of Spanner's transaction model, CockroachDB cannot achieve a delay of 10ms; CockroachDB's Commit Wait needs to be specified by the user, but who can tell how many milliseconds the clock error of NTP is? I personally think that in dealing with the problem of clock synchronization across intercontinental computer rooms, there is basically only one way to solve the problem of hardware clock synchronization. HLC cannot solve it. In addition, Cockroach uses gossip to synchronize node information. When the cluster becomes larger, gossip heartbeat will be a very large overhead. Of course, CockroachDB  The advantage of these technical choices is that they are very easy to use. All logic is in a binary and it is used out of the box. This is a very big advantage. "
 for i := 0; i &lt; 10000000; i++ {
  bf &lt;- ("%s%d", str, i)
 }
 ()
}func sprint(s string) {
 (1000 * )
}func get1(bf chan string)  {    for {        select {        case str := &lt;-bf:
            sprint(str)        case &lt;-(3 * ):
            ()
        }
    }
}

The above is personal experience. I hope you can give you a reference and I hope you can support me more. If there are any mistakes or no complete considerations, I would like to give you advice.