Easy Tutorial
❮ Java Printf Formate Demo Html5 Canvas Intro ❯

Go Channel Detailed Explanation

Category Programming Techniques

-Channel Type

-Blocking

-Buffered Channels

-Range

-Select

-Timeout

-Timer and Ticker

-Close

-Synchronization

-Reference Materials

A Channel in Go is a core type that can be thought of as a conduit through which concurrent core units can send or receive data for communication.

Its operator is the arrow <-.

ch <- v    // Send value v to Channel ch
v := <-ch  // Receive data from Channel ch and assign it to v

(The direction of the arrow represents the flow of data)

Like the map and slice data types, a channel must be created before it is used:

ch := make(chan int)

Channel Type

The definition format of the Channel type is as follows:

ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType .

It includes three types of definitions. The optional <- represents the direction of the channel. If the direction is not specified, the Channel is bidirectional, capable of both receiving and sending data.

chan T          // Can receive and send data of type T
chan<- float64  // Can only be used to send data of type float64
<-chan int      // Can only be used to receive data of type int

<- always binds with the type on the far left.

chan<- chan int    // Equivalent to chan<- (chan int)
chan<- <-chan int  // Equivalent to chan<- (<-chan int)
<-chan <-chan int  // Equivalent to <-chan (<-chan int)
chan (<-chan int)

Use make to initialize a Channel and you can set its capacity:

make(chan int, 100)

Capacity represents the maximum number of elements a Channel can hold, which is the size of the Channel's buffer.

You can close a Channel using the built-in close method.

You can receive/send data to/from a channel in multiple goroutines without the need for additional synchronization measures.

A Channel can act as a first-in-first-out (FIFO) queue, where the order of received and sent data is consistent.

The receive operation supports multi-valued assignment, such as

v, ok := <-ch

This can be used to check if the Channel has been closed.

-Send statement ch <- 3.

SendStmt = Channel "<-" Expression .
Channel  = Expression .

Before communication begins, the channel and expression must be evaluated first, such as calculating (3+4) to 7 before sending it to the channel.

c := make(chan int)
defer close(c)
go func() { c <- 3 + 4 }()
i := <-c
fmt.Println(i)

The send is blocked until the communication proceeds. As previously mentioned, a send on an unbuffered channel is executed only after the receiver is ready. If there is a buffer and it is not full, the send is executed.

Sending data to a channel that has already been closed will cause a run-time panic.

Sending data to a nil channel will always be blocked.

Receiving data from a nil channel will always be blocked.

Receiving data from a closed channel is not blocked but returns immediately, returning the zero value of the element type after all sent data has been received.

As mentioned earlier, you can use an additional return parameter to check if the channel is closed.

x, ok := <-ch
x, ok = <-ch
var x, ok = <-ch

If OK is false, it indicates that the received x is the zero value, and the channel is closed or empty.

Blocking

By default, sending and receiving will be blocked until the other party is ready. This method can be used for synchronization in goroutines without the need for explicit locks or conditional variables.

For example, in the official example x, y := <-c, <-c, this line will wait until the calculation result is sent to the channel.

import "
You can also use `timer.Stop` to stop a timer.

timer2 := time.NewTimer(time.Second) go func() { <-timer2.C fmt.Println("Timer 2 expired") }() stop2 := timer2.Stop() if stop2 { fmt.Println("Timer 2 stopped") }


A `ticker` is a timer that triggers at a regular interval, sending an event (the current time) to a Channel, and the receiver of the Channel can read events from the Channel at a fixed time interval. In the following example, the ticker triggers every 500 milliseconds, and you can observe the output time.

ticker := time.NewTicker(time.Millisecond * 500) go func() { for t := range ticker.C { fmt.Println("Tick at", t) } }()


Like a timer, a ticker can also be stopped using the `Stop` method. Once stopped, the receiver will no longer receive data from the channel.

## close

The built-in `close` method can be used to close a channel.

Summarize the operations of senders and receivers after a channel is closed. `panic: send on closed channel`:

import "time" func main() { go func() { time.Sleep(time.Hour) }() c := make(chan int, 10) c <- 1 c <- 2 close(c) c <- 3 }


However, not only can data already sent be read from this closed channel, but zero values can also be continuously read:

c := make(chan int, 10) c <- 1 c <- 2 close(c) fmt.Println(<-c) //1 fmt.Println(<-c) //2 fmt.Println(<-c) //0 fmt.Println(<-c) //0


But if reading with `range`, the for loop will exit after the channel is closed:

c := make(chan int, 10) c <- 1 c <- 2 close(c) for i := range c { fmt.Println(i) }


The status of the Channel can be checked with `i, ok := <-c` to determine whether the value is a zero value or a normally read value.

c := make(chan int, 10) close(c) i, ok := <-c fmt.Printf("%d, %t", i, ok) //0, false


---

## Synchronization

Channels can be used for synchronization between goroutines.

import ( "fmt" "time" ) func worker(done chan bool) { time.Sleep(time.Second) // Notify that the task is complete done <- true } func main() { done := make(chan bool, 1) go worker(done) // Wait for the task to complete <-done } ```

>

Source: http://colobu.com/2016/04/14/Golang-Channels/

❮ Java Printf Formate Demo Html5 Canvas Intro ❯