Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Start a free Courses trial
to watch this video
Channels solve two problems simultaneously: they let your goroutines communicate with each other, and they let you synchronize your goroutines' operations.
Here's an updated version of our longTask
function that takes a random number of seconds to complete. We're using the rand
package to generate a random number. We've also updated longTask
to return the number of seconds it took to its caller.
package main
import (
"fmt"
"math/rand"
"time"
)
func longTask() int {
delay := rand.Intn(5)
fmt.Println("Starting long task")
time.Sleep(time.Duration(delay) * time.Second)
fmt.Println("Long task finished")
return delay
}
func main() {
rand.Seed(time.Now().Unix())
time := longTask()
fmt.Println("Took", time, "seconds")
}
- Suppose we want to call
longTask
as a goroutine. We can't just saytime := go longTask()
. We'll get a syntax error if we try to run this. - And even if that were allowed, what would we print in the like following the call to
longTask
? The goroutine doesn't return a value right away! - It's just not possible to communicate between goroutines using simple return values.
So instead, we're going to create a channel, and use that to communicate with our goroutine. The channel will allow longTask
to pass a value back to the main
goroutine. And when the main
goroutine encounters the instruction to read from the channel, it will wait until it has a value to proceed.
- We call the built-in
make
method to create a channel. The type for a channel ischan
. And then we need to specify what type of values the channel will accept; we'll useint
. - We're going to change
longTask
's declaration so it accepts a channel as an argument, and get rid of the return value. So we'll pass our new channel tolongTask
, get rid of thetime
variable, and call it as a goroutine. - Then, instead of printing the
time
variable, we'll read a value from the channel. - Then we'll change the
longTask
declaration to match the call inmain
. We'll accept achan int
parameter, and get rid of the return value. - Instead of returning the time we waited at the end of
longTask
, we're going to write that value to the channel. That value will then be received and printed down inmain
.
package main
import (
"fmt"
"math/rand"
"time"
)
func longTask(channel chan int) { // Remove return value, accept channel chan int
delay := rand.Intn(5)
fmt.Println("Starting long task")
time.Sleep(time.Duration(delay) * time.Second)
fmt.Println("Long task finished")
channel <- delay // Changed from "return delay"
}
func main() {
rand.Seed(time.Now().Unix())
channel := make(chan int) // Add
go longTask(channel) // Change from "time := longTask()"
fmt.Println("Took", <-channel, "seconds") // "<-channel" instead of "time"
}
- We can start multiple goroutines if we want, and they can all write to the same channel.
- Then as long as we read from the channel that same number of times, the program will wait until all goroutines have finished before it exits.
for i := 1; i <= 3; i++ {
go longTask(channel)
}
for i := 1; i <= 3; i++ {
fmt.Println("Took", <-channel, "seconds")
}
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up