Home  >  Article  >  Backend Development  >  Advanced usage of Goroutines and Channels in Golang

Advanced usage of Goroutines and Channels in Golang

PHPz
PHPzOriginal
2023-08-07 12:12:211122browse

Advanced usage of Goroutines and Channels in Golang

In concurrent programming in Golang, Goroutines and Channels are two very important concepts. Goroutines are lightweight threads that can execute concurrently, while Channels are the communication mechanism between Goroutines. In this article, we will explore the advanced usage of Goroutines and Channels in Golang and illustrate it with code examples.

1. Advanced usage of Goroutines

  1. The multiplexing of Goroutines can be achieved through the select statement. In the code example below, we create two Goroutines to calculate the Fibonacci sequence and factorial respectively. Through the select statement, we can wait for two Goroutines to complete at the same time and print out the calculation results.
package main

import (
    "fmt"
)

func fibonacci(n int, c chan<- int) {
    x, y := 0, 1
    for i := 0; i < n; i++ {
        c <- x
        x, y = y, x+y
    }
    close(c)
}

func factorial(n int, c chan<- int) {
    result := 1
    for i := 1; i <= n; i++ {
        result *= i
    }
    c <- result
    close(c)
}

func main() {
    fibChan := make(chan int)
    factChan := make(chan int)

    go fibonacci(10, fibChan)
    go factorial(5, factChan)

    for {
        select {
        case fib, ok := <-fibChan:
            if ok {
                fmt.Println("Fibonacci:", fib)
            } else {
                fibChan = nil
            }

        case fact, ok := <-factChan:
            if ok {
                fmt.Println("Factorial:", fact)
            } else {
                factChan = nil
            }

        default:
            if fibChan == nil && factChan == nil {
                return
            }
        }
    }
}
  1. You can wait for the completion of Goroutines through WaitGroup. WaitGroup is a counter that can be used to wait for the completion of a group of Goroutines. In the code example below, we create two Goroutines to calculate the Fibonacci sequence and factorial respectively. With sync.WaitGroup, we can wait for two Goroutines to complete simultaneously.
package main

import (
    "fmt"
    "sync"
)

func fibonacci(n int, c chan<- int, wg *sync.WaitGroup) {
    defer wg.Done()
    x, y := 0, 1
    for i := 0; i < n; i++ {
        c <- x
        x, y = y, x+y
    }
    close(c)
}

func factorial(n int, c chan<- int, wg *sync.WaitGroup) {
    defer wg.Done()
    result := 1
    for i := 1; i <= n; i++ {
        result *= i
    }
    c <- result
    close(c)
}

func main() {
    fibChan := make(chan int)
    factChan := make(chan int)
    var wg sync.WaitGroup

    wg.Add(2)

    go fibonacci(10, fibChan, &wg)
    go factorial(5, factChan, &wg)

    go func() {
        wg.Wait()
        close(fibChan)
        close(factChan)
    }()

    for {
        select {
        case fib, ok := <-fibChan:
            if ok {
                fmt.Println("Fibonacci:", fib)
            } else {
                fibChan = nil
            }

        case fact, ok := <-factChan:
            if ok {
                fmt.Println("Factorial:", fact)
            } else {
                factChan = nil
            }

        default:
            if fibChan == nil && factChan == nil {
                return
            }
        }
    }
}

2. Advanced usage of Channels

  1. You can control the blocking behavior of Channel by setting the buffer size. By default, Channel is unbuffered, that is, sending and receiving will block until the other party is ready. We can set the buffer size through the second parameter of the make function. In the following code example, we create a Channel with a buffer size of 3 and send 3 values ​​to it. Since the buffer is not full, the send does not block.
package main

import (
    "fmt"
)

func main() {
    ch := make(chan int, 3)
    ch <- 1
    ch <- 2
    ch <- 3

    fmt.Println(<-ch)
    fmt.Println(<-ch)
    fmt.Println(<-ch)
}
  1. Channel can be iterated through the range keyword. The range keyword can be used to iterate the values ​​in the Channel. When the Channel is closed, the iteration will automatically end. In the following code example, we create a counter Goroutines and send 5 values ​​to an unbuffered Channel. In the main function, we use the range keyword to iterate the values ​​in the Channel and print them out. When the Channel is closed, the range loop will automatically end.
package main

import (
    "fmt"
    "time"
)

func counter(ch chan<- int) {
    for i := 1; i <= 5; i++ {
        ch <- i
        time.Sleep(time.Second)
    }
    close(ch)
}

func main() {
    ch := make(chan int)
    go counter(ch)

    for val := range ch {
        fmt.Println(val)
    }
}

To sum up, Goroutines and Channels in Golang provide powerful and flexible concurrent programming capabilities. We have more control over the behavior of Goroutines and Channels through advanced usage such as select statements, WaitGroup, buffers, and range keywords. We hope that the code examples given in this article can help readers better understand and apply these advanced usages.

The above is the detailed content of Advanced usage of Goroutines and Channels in Golang. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn