Channels
A way of sending data between threads
Channels block until a message can be retrieved
This is Go’s way of thread safety
ch <- v // Send v to channel ch.
v := <-ch // Receive from ch, and
// assign value to v.
func sum(vals []int, cn chan int) {
acc := 0
for _, val := range vals {
acc += val
}
cn <- acc
}
func main() {
vals := []int{1, 3, 5}
cn := make(chan int)
halfWay := len(vals) / 2
go sum(vals[:halfWay], cn)
go sum(vals[halfWay:], cn)
total := <-cn + <-cn
fmt.Printf("total: %v", total)
}
// output
// total: 9Buffers
When a channel is filled to the buffer, all further entries will be blocked until there is room
func main() {
ch := make(chan int, 2) // <- 2 is the buffer size
ch <- 1
ch <- 2
// ch <- 3
fmt.Println(<-ch)
fmt.Println(<-ch)
}Close
You can close a channel, which will then stop you from being able to add entries
You can test if the channel is closed and has no values by using the ok strat
func main() {
cn := make(chan int, 10)
for i := 0; i < 10; i++ {
cn <- i
}
close(cn)
if val, ok := <-cn; ok {
fmt.Printf("you can still get things %v\n", val)
} else {
fmt.Println("closed and no values left")
}
}For range
You can create a loop that infinitely just eats off a channel, until its is closed and no entires
Note: that the output is not as expected. You will need to use the sync lib to resolve that
func eater(cn chan int) {
for val := range cn {
fmt.Printf("%v,", val)
}
fmt.Println("\nNo more values")
}
func main() {
cn := make(chan int, 10)
go eater(cn)
for i := 0; i < 10; i++ {
time.Sleep(1 * time.Second)
cn <- i
}
close(cn)
}
// Output
// 0,1,2,3,4,5,6,7,8,