User Tools

Site Tools


go:concurrency:select

This is an old revision of the document!


Go select with Non-blocking Send and Receive

Overview

In Go, the select statement allows a goroutine to wait on multiple channel operations. When combined with a default case, select can be used to perform non-blocking send and receive operations on channels.

📌 non-blocking /nɒn ˈblɒk.ɪŋ/ → does not wait; continues immediately

Basic Concept

Normally, sending to or receiving from a channel may block if:

the channel is full (send)

the channel is empty (receive)

no goroutine is ready on the other side

Using select with default avoids blocking by trying once and moving on.

📌 block /blɒk/ → pause execution and wait

Non-blocking Send

A non-blocking send attempts to send a value on a channel without waiting.

Syntax

 select { case ch <- value: // send succeeded default: // send would block, so skip } 

Explanation

If the channel can accept the value:

the send happens immediately

If the channel cannot accept the value:

the default case runs

the goroutine continues execution

📌 attempt /əˈtempt/ → try to do something

📌 accept /əkˈsept/ → receive or take in

Non-blocking Receive

A non-blocking receive attempts to receive a value only if one is available.

Syntax

 select { case value := <-ch: // receive succeeded default: // no value available } 

Explanation

If a value is available:

it is received immediately

If no value is available:

default executes

execution continues without waiting

📌 receive /rɪˈsiːv/ → get or take something

📌 available /əˈveɪ.lə.bəl/ → ready to be used

Buffered vs Unbuffered Channels

Unbuffered Channel

 ch := make(chan int) 

Send and receive must happen at the same time

Non-blocking send will fail if no receiver is ready

Used for synchronization

📌 synchronization /ˌsɪŋ.krə.naɪˈzeɪ.ʃən/ → coordinating actions to happen together

Buffered Channel

 ch := make(chan int, 2) 

Channel can hold values temporarily

Non-blocking send succeeds if buffer is not full

Non-blocking receive succeeds if buffer is not empty

📌 buffer /ˈbʌf.ər/ → temporary storage area

Common Mistakes

Ignoring the result of append-like behavior

 select { case ch <- v: default: } 

If the send fails, the value is silently dropped.

📌 silently /ˈsaɪ.lənt.li/ → without any warning or message

Using len(ch) to decide send/receive

This is unsafe:

 if len(ch) < cap(ch) { ch <- v // race condition } 

📌 race condition /reɪs kənˈdɪʃ.ən/ → bug caused by timing between goroutines

Always prefer select.

When to Use Non-blocking Channel Operations

Use non-blocking send/receive when:

you want to avoid deadlocks

dropping data is acceptable

implementing polling or event loops

building soft real-time systems

📌 deadlock /ˈded.lɒk/ → program stops because goroutines wait on each other

📌 polling /ˈpəʊ.lɪŋ/ → checking repeatedly

Key Takeaways

select + default enables non-blocking behavior

Non-blocking send = try to send once, never wait

Non-blocking receive = try to receive once, never wait

Works best with buffered channels

Safe and idiomatic Go concurrency pattern

go/concurrency/select.1769814605.txt.gz · Last modified: by phong2018