# Golang Concurrency #4 - Channel operations

# Send and Receive (Covered in previous post)

```go
ch <- value    // Send
value := <-ch  // Receive
```

# Closing Channels

```go
close(ch)
```

* Signals "no more values will be sent"
    
* Receivers can still read remaining values
    
* Sending to closed channel = panic
    

# Checking if channel is closed

```go
value, ok := <-ch
if !ok {
    // Channel is closed and empty
}
```

# Buffered vs Unbuffered Channels

## Unbuffered (default)

```go
ch := make(chan int)  // Buffer size 0
```

* Sender blocks until receiver is ready
    
* Receiver blocks until sender sends
    
* Synchronous handoff
    

## Buffered

```go
ch := make(chan int, 3)  // Buffer size 3
```

* Sender only blocks when buffer is full
    
* Receiver only blocks when buffer is empty
    
* Asynchronous up to buffer size
    

## Buffered example

```go
ch := make(chan int, 2)

ch <- 1  // Doesn't block, buffer has space
ch <- 2  // Doesn't block, buffer has space
ch <- 3  // BLOCKS! Buffer is full

fmt.Println(<-ch)  // Prints 1, frees buffer space
ch <- 3            // Now this works
```

## When to use buffered

* When you want to decouple sender/receiver timing
    
* When you know how many items you'll process
    
* For performance (reduce blocking)
    

## When to use unbuffered

* When you want synchronization (sender waits for receiver)
    
* For simple request-response patterns
    
* When you want guaranteed delivery
    

# More notes

## Receiving removes from channel

```go
ch := make(chan int, 2)
ch <- 10
ch <- 20

first := <-ch   // Takes 10 out of channel
second := <-ch  // Takes 20 out of channel
third := <-ch   // Channel is now empty, this blocks
```

Once you receive a value, it's gone from the channel.

## Buffer is exactly like a queue (FIFO - First In, First Out)

```go
ch := make(chan int, 3)

ch <- 1  // Queue: [1]
ch <- 2  // Queue: [1, 2]
ch <- 3  // Queue: [1, 2, 3]

fmt.Println(<-ch)  // Gets 1, Queue: [2, 3]
fmt.Println(<-ch)  // Gets 2, Queue: [3]
fmt.Println(<-ch)  // Gets 3, Queue: []
```

## Non-blocking = other code runs

```go
ch := make(chan int, 2)

ch <- 1         // Doesn't block, continues immediately
ch <- 2         // Doesn't block, continues immediately
fmt.Println("This runs right away!")

ch <- 3         // NOW it blocks, waiting for buffer space
fmt.Println("This waits until someone receives")
```

## Blocking = everything stops

```go
ch := make(chan int)  // Unbuffered

ch <- 1  // BLOCKS here, waiting for receiver
fmt.Println("This never runs until someone receives")
```
