Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Go Language Go Language Overview Concurrency Channels

My notes on channels

package main

import (
  "fmt"
  "math/rand"
  "time"
)

func longTask(channel chan int) {  // type chan, type chan holds is int. No return value
  delay := rand.Intn(5)  // get random number
  fmt.Println("Starting long task")
  time.Sleep(time.Duration(delay) * time.Second) // sleeps random  number of seconds 
  fmt.Println("Long task finished")
  //  return delay  // return doesn't work with goroutines
  channel <- delay // delay INTO channel
}

func main() {
  rand.Seed(time.Now().Unix())
  //  time := longTask()  // old linear way
  //  time := go longTask()  // error: unexpected go, expects expression
  channel := make(chan int)
  go longTask(channel)

  // read from channel causes main goroutine to wait
  // until longTask() goroutine finishes.
  // Solves problem of main() goroutine exiting before longTask() done
  // Communicates between routines, and synches them up
  fmt.Println("Took", <-channel, "seconds")  // read value from channel
                                             // arrow pointing FROM channel INTO your code
                                             // or channel INTO code


  // multiple goroutines can write to same channel
  for i := 1;i <= 3; i++ {
    go longTask(channel)  // call longTask() 3x goroutines
  }

  for i := 1; i <= 3; i++ {
    // Because we read from channel 
    // the same number of times we wrote to it,
    // the program aka main(), 
    // waits till GoRoutines have finished before it exits
    fmt.Println("Took", <-channel, "seconds")
  }
}

/*
Notes:
channels - 1. lets go routines communicate with each other 
           2. synchronizes go routines

Issue:
Not possible to communicate between go routines using return values.

go routine 1 can't return value that go routine 2 can use uses.

Go Routines suffer from familiar asynchronous programming issues.
Code is sequential, but returns are asynchronous.
JavaScript fixes this with promises and async/await.

Solution:
Go uses channels. 

similarities:
go -> async
channel -> await.

When main go routine encounters channel,
it waits until it has a value to proceed.

Differences compared to JavaScript/NodeJS:
1. Go is deep coroutines. Pausing them captures the entire stack
A calls B. 
B calls C. 
C is able to stop execution of A.
A -> B -> C. C can stop A.

JavaScript is shallow coroutines. Pausing them only captures 
the current function's stack
A calls B
B calls C
C is only able to stop C. Not A or B.

See:
https://www.quora.com/Is-async-await-in-Node-js-similar-to-Goroutines

2. Instead of sharing global state, 
the coroutines communicate state through channels 

5. NodeJS is single threaded
NodeJS implements a simple form of concurrency 
thru non-blocking I/O (input/output)
It doesn't block other computation from happening 
while waiting for values.
async/await and Promises are abstractions on top of this.
So NodeJS is only async I/O (input/output)

Go is multi threaded.
Go supports true concurrency with access to CPU cores.
Not only async I/I(input/output).

If goroutines takes extra CPU time, 
it will move data to different CPU threads
and is still executed.

see: https://codeburst.io/why-goroutines-are-not-lightweight-threads-7c460c1f155f

syntax:
chan - channel
channel := make(chan int) - make channel with int value it will accept
<-  - The <- operator means put or get message from a channel.
      The <- operator represents the idea of passing a value 
        from a channel to a reference.
      Think of the channel as a queue.
        Using an assignment operator = would assign the reference to the queue 
        to the target variable. 
      The receive operator <- is equivalent to dequeuing from the queue 
        and assigning the value of the item to the target variable.
<-channel - read value from channel


Difference between = and <- in GoLang:
https://stackoverflow.com/questions/33325395/what-is-the-difference-between-and-in-golang

How to write common JS code in Go:
see: https://levelup.gitconnected.com/use-go-channels-as-promises-and-async-await-ee62d93078ec
*/