-1

I have following code

import (
    "fmt"
)

func access(ch chan int) {
    for elem := range ch {
        fmt.Println(elem) // prints only one as well
    }
    fmt.Println(<-ch) // prints the value
    fmt.Println(<-ch) // doesn't print

}
func main() {

    ch := make(chan int)

    go access(ch)
    ch <- 55 // blocks the main routine
    ch <- 56 // this value never prints

    fmt.Println("Hello, World!")
}

Why only the first value sent through channel gets printed not the other one ,even with for loop ,inspite of using unbuffered channel

If I use a for loop to send values it works

  arr:=[]int{1, 1, 1, 1, 1}
 for elem := range arr {
      ch<-elem
    }

Here is another mystery ,if I add three values sending to ch.All values gets printed in the access function .this is bit strange .....................

 func access(ch chan int){
      /*
        for elem := range ch {
            fmt.Println(elem)
        }
        */
// All prints
      fmt.Println(<-ch)
      fmt.Println(<-ch)
        fmt.Println(<-ch)
    
    }
    func main() {
    
  
    
    go access(ch)
     
    ch<-55
    ch<-56
    ch<-57
    
        
    }
trinity
  • 159
  • 1
  • 7
  • 20
  • When the `main` goroutine ends, you're app may end as well, immediately, without waiting other goroutines to continue or finish. When the second value is received from `ch`, `main()` can advance, print, and end. Without explicit synchronization, there's no guarantee the other goroutine can print the received value. Any outcome is valid and does not violate the language spec. If you need guarantee for the other goroutine to finish, use synchronization, e.g. `sync.WaitGroup`. – icza Jan 03 '22 at 08:26

1 Answers1

1

After sending the first value, the main goroutine is blocked by the second send operation, until the first one is processed, that's why the first number is printed even without waiting on the main side. (I'm not sure that this behavior is guaranteed by the scheduler, most likely, not.) But after sending the second value, main exits immediately, without giving the other goroutine a chance to finish. You may want to wait for the goroutine to complete first:

package main

import (
    "fmt"
    "sync"
)

func access(ch chan int) {
    fmt.Println(<-ch) // prints the value
    fmt.Println(<-ch) // doesn't print
}

func main() {

    ch := make(chan int)

    var wg sync.WaitGroup
    wg.Add(1)
    go func() {
        access(ch)
        wg.Done()
    }()
    ch <- 55
    ch <- 56
    wg.Wait()

    fmt.Println("Hello, World!")
}
bereal
  • 32,519
  • 6
  • 58
  • 104
  • Yeah that I know but why it prints the first and don't exit before that ,why only for other ones .That is the question – trinity Jan 03 '22 at 07:21
  • Ok I get that ,but what If I send three values ,it just prints all three :/ see updated question – trinity Jan 03 '22 at 07:36
  • @trinity this also may happen, it's just not guaranteed by the scheduler. – bereal Jan 03 '22 at 07:37
  • Ok ,so is this scheduler depends on type of os ? – trinity Jan 03 '22 at 07:47
  • @trinity Go runtime has its own goroutine scheduler, and the underlying mechanisms are OS-dependent. There are some [nice](https://medium.com/@ankur_anand/illustrated-tales-of-go-runtime-scheduler-74809ef6d19b) [articles](https://www.ardanlabs.com/blog/2018/08/scheduling-in-go-part1.html) about the details. – bereal Jan 03 '22 at 08:51