English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Golang Basic Tutorial

Golang Control Statements

Golang Function & Method

Golang Struct

Golang Slice & Array

Golang String (String)

Golang Pointer

Golang Interface

Golang Concurrency

Golang Exception (Error)

Golang Other Miscellaneous

Go Language Channel (Channel)

In Go language, channels are the means by which goroutines communicate with each other, and this communication is lock-free. In other words, a channel is a technique that allows one goroutine to send data to another goroutine. By default, channels are bidirectional, which means that goroutines can send or receive data through the same channel, as shown in the following figure:

Create a channel

In Go language, a channel is created using the chan keyword, and the channel can only transmit data of the same type, and it is not allowed to transmit different types of data from the same channel.

Syntax:

var Channel_name chan Type

You can also use a shorthand declaration to create a channel with the make() function.

Syntax:

channel_name:= make(chan Type)
package main
import "fmt"
func main() {
    //A channel is created using the var keyword
    var mychannel chan int
    fmt.Println("Channel value: ", mychannel)
    fmt.Printf("Channel type: %T ", mychannel)
    // Use the make() function to create a channel
    mychannel1 := make(chan int)
    fmt.Println("\nchannel1Value:", mychannel1)
    fmt.Printf("channel1Type: %T ", mychannel1)
}

Output:

Channel value: <nil>
Channel type: chan int
channel1Value: 0xc0000160c0
channel1Type: chan int

Sending and receiving data from a channel

In Go language, there are two main operations for channels: one is sending and the other is receiving, which are collectively called communication.-The direction of the operator indicates whether to receive or send data. By default, in channels, send and receive operations block until there is no data at the other end. It allows goroutines to synchronize with each other without explicit locks or condition variables.

  1. Send operation:The send operation is used to send data from one goroutine to another with the help of a channel. Similar to int, float64Values like bool can be safely and easily sent through channels because they are copied, thus eliminating the risk of concurrent access to the same value. Similarly, strings are safe because they are immutable. However, sending pointers or references (such as slices, map sets, etc.) through channels is not safe because the value of pointers or references may change through concurrent sending or receiving goroutines, and the result is unpredictable. Therefore, when using pointers or references in channels, it must be ensured that they can only be accessed by one goroutine at a time.

    Mychannel <- element

    The above statement indicates that the data (element) is<-operator to send to the channel (Mychannel).

  2. Receive operation:The receive operation is used to receive the data sent by the sender of the send operation.

    element := <-Mychannel

    The above statement indicates that the element is receiving data from the channel (Mychannel). If the result of the received statement is not available (not needed to use), it is also a valid statement. You can also write the following receive statement:

    <-Mychannel
package main 
  
import "fmt"
  
func myfunc(ch chan int) { 
  
    fmt.Println(234 + <-ch) 
} 
func main() { 
    fmt.Println("Main method starts") 
    //Create channel l 
    ch := make(chan int) 
  
    go myfunc(ch) 
    ch <- 23 
    fmt.Println("Main method ends") 
}

Output:

Main method starts
257
Main method ends

Close the channel

You can also close the channel with the help of the close() function. This is a built-in function that sets a flag indicating that no more values will be sent to the channel.

Syntax:

close()

You can also use a for range loop to close the channel. Here, the receiver goroutine can use the given syntax to check whether the channel is open or closed:

ele, ok := <- Mychannel

Here, if the value of ok is true, it indicates that the channel is open, so read operations can be performed. And if the value is false, it indicates that the channel is closed, so the read operation will not be executed.

//The Go program explains how
//Close the channel used
//range loop and close function
package main
import "fmt"
func myfun(mychnl chan string) {
    for v := 0; v < 4; v++ {
        mychnl <- "w3codebox
    }
    close(mychnl)
}
func main() {
    //Create a channel
    c := make(chan string)
    // Using Goroutine
    go myfun(c)
    //When the value of ok is true, it indicates that the channel is open, and data can be sent or received
    //When the value of ok is set to false, it indicates that the channel has been closed
    for {
        res, ok := <-c
        if ok == false {
            fmt.Println("Channel closed", ok)
            break
        }
        fmt.Println("Channel opened", res, ok)
    }
}

Output:

Channel opened w3codebox true
Channel opened w3codebox true
Channel opened w3codebox true
Channel opened w3codebox true
Channel closed false

Important Notes

  • Blocking send and receive:In a channel, when data is sent to a channel, control is blocked in the send statement until another goroutine reads data from the channel. Similarly, when a channel is read by a goroutine, the read statement block until another goroutine statement.

  • Zero-valued channel: A channelis nil.

  • For loop in channels: The for loop can iterate over the ordered values sent on a channel until it is closed.

    Syntax:

    for item := range Chnl { 
         // statement...
    }
    package main 
    import "fmt"
      
    func main() { 
      
        // Use the make() function to create a channel
        mychnl := make(chan string) 
      
        // Anonymous goroutine 
        go func() { 
            mychnl <- "GFG"
            mychnl <- "gfg"
            mychnl <- "Geeks"
            mychnl <- "w3codebox
            close(mychnl) 
        } 
      
        //Use a for loop
        for res := range mychnl { 
            fmt.Println(res) 
        } 
    }

    Output:

    GFG
    gfg
    Geeks
    w3codebox
  • Channel length:In a channel, you can uselen() functionFind the channel length. Here, the length represents the number of values queued in the channel buffer.

    package main 
      
    import "fmt"
    func main() { 
      
        // Use the make() function to create a channel 
        mychnl := make(chan string, 4) 
        mychnl <- "GFG"
        mychnl <- "gfg"
        mychnl <- "Geeks"
        mychnl <- "w3codebox
        // Use the len() function to find the channel length 
        fmt.Println("Channel length:", len(mychnl)) 
    }

    Output:

    Channel length is:  4
  • Channel capacity:In a channel, you can use the cap() function to find the channel capacity. Here, the capacity represents the size of the buffer.

    package main
    import "fmt"
    func main() {
        // Use the make() function to create a channel
        mychnl := make(chan string, 4)
        mychnl <- "GFG"
        mychnl <- "gfg"
        mychnl <- "Geeks"
        mychnl <- "w3codebox
        // Use the cap() function to find the channel capacity
        fmt.Println("Channel capacity:", cap(mychnl))
    }

    Output:

    Channel capacity is:  5
  • Channel Select and Case Statements:In Go language, the select statement is like a switch statement without any input parameters. The select statement is used in channels to execute a single operation from multiple operations provided by the case blocks.