Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it better to range over channel or use select?

Tags:

go

guys i was wondering if it is better to to range over channel or use select, if I have only one case (my channel) and signal the end with close of the given channel ?

Given the examples:

1. https://play.golang.org/p/3ZFdbgHSKyN

go func() {
    for v := range ch {
        // do some stuff
    }
}()

2. https://play.golang.org/p/iCCkDge8j72

go func() {
    for {
        select {
        case v, ok := <-ch:
            if !ok {
                return
            }

            // do some stuff
        }
    }
}()

Which solution would be preferred and why ? Please consider the fact that goroutines as such might be spawned many times (many workers).

like image 251
vardius Avatar asked May 15 '19 05:05

vardius


People also ask

Can we use for range through a channel?

The range keyword can also be used on a channel. By doing so, it will iterate over every item thats send on the channel. You can iterate on both buffered and unbuffered channels, but buffered channels need to be closed before iterating over them.

What are the differences between unbuffered and buffered channels?

When a channel is created with no capacity, it is called an unbuffered channel. In turn, a channel created with capacity is called a buffered channel. To understand what the synchronization behavior will be for any goroutine interacting with a channel, we need to know the type and state of the channel.

Are Go channels blocking?

Channel operation (i.e. write or read) are blocking in nature. This means: When we send data into the channel using a GoRoutine, it will be blocked until the data is consumed by another GoRoutine. When we receive data from channel using a GoRoutine, it will be blocked until the data is available in the channel.

What is a Goroutine?

A goroutine is a function that executes simultaneously with other goroutines in a program and are lightweight threads managed by Go. A goroutine takes about 2kB of stack space to initialize.


1 Answers

Unless there's another branch of the select, use the following:

for v := range ch {
    // do some stuff
}

The code is simpler and easier to understand than the for/select presented in the question.

If you need to do the receive inside the loop for some reason, then use the following code:

 for  { 
     // do some stuff
     v, ok := <-ch
     if !ok { 
        break 
     } 
     // do some other stuff
 }

As a rule of thumb, single branch select statements should be avoided. A select with a single branch is functionally the same as the branch alone.

like image 186
Bayta Darell Avatar answered Nov 15 '22 09:11

Bayta Darell