You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesi贸n a prueba de IA

Antes: $249

Currency
$209
Suscr铆bete

Termina en:

0 D铆as
3 Hrs
11 Min
26 Seg

Multiplexaci贸n con Select y Case

27/30
Resources

How does multiplexing with channels work in Go?

Concurrent scheduling is essential to optimize performance and efficiency. In Go, channels are a key tool for communicating between goroutines. However, what do you do when you have multiple channels and need to manage the arrival of data non-sequentially? This is where the use of select to implement multiplexing comes into play.

How do you configure a channel in Go?

To begin with, we need to understand how channels are configured in Go. Channels allow communication and synchronization between different goroutines.

package main
import ("fmt""time")
func doSomething(duration time.Duration, channel chan int, param int) {time.Sleep(duration)channel <- param}
func main() {c1 := make(chan int)c2 := make(chan int)
duration1 := 4 * time.Secondduration2 := 2 * time.Second
go doSomething(duration1, c1, 1)go doSomething(duration2, c2, 2)
for i := 0; i < 2;  i++ {select {case msg1 := <-c1:fmt.Printf("Channel 1 received: %d\n", msg1)case msg2 := <-c2:fmt.Printf("Channel 2 received: %d\n", msg2)}} }} } }

What is and how does the select operator in Go work?

Select is a switch-like structure that allows you to listen to multiple channels at the same time, executing the case that is ready first. It allows you to handle message arrivals more flexibly than a sequential approach.

  • Select: Allows a goroutine to wait on multiple communication operations.
  • Case: Similar to the cases in a switch, each represents a channel from which it is listening.

In the example above, select is used to print the message from the channel that first sends a signal, avoiding blocking while waiting for another operation.

Why use select instead of a sequential approach?

When concurrently handling multiple processes, the sequential approach can block the execution of faster tasks because it is waiting for a response from slower ones. Select solves this problem by allowing more efficient, real-time handling of signals.

  • Practical example: The code demonstrates that, although the second channel finishes faster, the output of the first channel is not blocked. This is short-lived when the order of messages is relevant.

The use of select is particularly useful in systems where latency is crucial or certain tasks are expected to finish at different times. This is where Go, with this operator, shows its robustness in handling concurrency without sacrificing performance.

What are the advantages of using select and case?

  • Efficiency: Responds faster to the first ready channel, optimizing response time.
  • Non-sequential: Eliminates dependence on a predefined order, vital for real-time applications.
  • Flexibility: Enables you to execute different code paths depending on which channel is ready.

With this knowledge, you can greatly improve your concurrent applications, making them responsive and efficient. Don't hesitate to implement select in your future developments and you will see the difference in performance, keep exploring and learning!

Contributions 5

Questions 0

Sort by:

Want to see more contributions, questions and answers from the community?

otro ejemplo de select y case: https://tour.golang.org/concurrency/5
Case

Code:

package main

import (
	"fmt"
	"time"
)

func doSomething(i time.Duration, c chan<- int, param int) {
	time.Sleep(i)
	c <- param
}

func main() {
	c1 := make(chan int)
	c2 := make(chan int)

	d1 := 4 * time.Second
	d2 := 2 * time.Second

	go doSomething(d1, c1, 1)
	go doSomething(d2, c2, 2)

	for i := 0; i < 2; i++ {
		select {
		case channelMsg1 := <-c1:
			fmt.Println(channelMsg1)
		case channelMsg2 := <-c2:
			fmt.Println(channelMsg2)
		}
	}
}

package main

import (
	"fmt"
	"time"
)

func doSomething(i time.Duration, c chan<- int, param int) {
	time.Sleep(i)
	c <- param
}

func main() {
	c1 := make(chan int)
	c2 := make(chan int)

	d1 := 4 * time.Second
	d2 := 2 * time.Second

	go doSomething(d1, c1, 1)
	go doSomething(d2, c2, 2)

	/* fmt.Println("Waiting for the first result")
	fmt.Println(<-c1)
	fmt.Println("Waiting for the second result")
	fmt.Println(<-c2) */

	for i := 0; i < 2; i++ {
		select {
		case res := <-c1:
			fmt.Println("Received", res, "from c1")
		case res := <-c2:
			fmt.Println("Received", res, "from c2")
		}
	}

}

Code

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func doSomething(i time.Duration, c chan<- int, param int) {
	time.Sleep(i)
	c <- param
}

func main() {
	c1 := make(chan int)
	c2 := make(chan int)

	// generate random number
	rand.Seed(time.Now().UnixNano())
	d1 := time.Duration(rand.Intn(10)) * time.Second
	d2 := time.Duration(rand.Intn(10)) * time.Second

	go doSomething(d1, c1, 1)
	go doSomething(d2, c2, 2)

	/* fmt.Println("Waiting for the first result")
	fmt.Println(<-c1)
	fmt.Println("Waiting for the second result")
	fmt.Println(<-c2) */

	for i := 0; i < 2; i++ {
		// wait for the completion of tasks
		select {
		case res := <-c1:
			fmt.Println("Received", res, "from c1 after", d1)
		case res := <-c2:
			fmt.Println("Received", res, "from c2 after", d2)
		}
	}

}

En Go tambi茅n tenemos el default case como los tradicionales switch-case 馃敟

https://go.dev/tour/concurrency/6