FAQ
Hi

I'm trying to understand ranging over channels. In the Golang spec it says:

     For channels, the iteration values produced are the successive values
sent on the channel until the channel is closed. If the channel is nil, the
range expression blocks forever.

For closing, the reference says:

     For a channel c, the built-in function close(c) records that no more
values will be sent on the channel.

And there are plenty of examples that invoke close() explicitly. But I am
also seeing from time to time examples that don't explicitly call close.
Here is one from
http://golangtutorials.blogspot.com/2011/06/channels-in-go-range-and-select.html

package main

import (
     "fmt"
     "time"
     "strconv"
)

func makeCakeAndSend(cs chan string, count int) {
     for i := 1; i <= count; i++ {
         cakeName := "Strawberry Cake " + strconv.Itoa(i)
         cs <- cakeName //send a strawberry cake
     }
}

func receiveCakeAndPack(cs chan string) {
     for s := range cs {
         fmt.Println("Packing received cake: ", s)
     }
}

func main() {
     cs := make(chan string)
     go makeCakeAndSend(cs, 5)
     go receiveCakeAndPack(cs)

     //sleep for a while so that the program doesn’t exit immediately
     time.Sleep(3 * 1e9)
}

This code doesn't call close(). So how does it work? Does ranging over
channels just run until there are no more messages left on the channel? And
then messages that come in after it happened to be drained simply have to
wait for the next send? If so, why does the documentation mention that
ranging works until a channel is closed? Or is that channel actually closed?




--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Chris Kastorff at May 13, 2016 at 5:27 pm
    In the code you sent, `cs` is never closed, and `receiveCakeAndPack` never
    exits. It's not good style to leave a reader hanging like that, since they
    become hard or impossible to clean up and thus leak resources.

    If you kill the program with SIGQUIT (ctrl-\ on unix terminals) after it
    writes the stuff but before it finishes sleeping, you'll see that it is
    still running.

    A better style, more appropriate to real applications, would be to have
    `makeCakeAndSend` effectively take ownership of the write half of the
    channel and close it explicitly when it's done, and have `main` call
    `recieveCakeAndPack` synchronously (without the `go` keyword.)
    On Fri, May 13, 2016 at 10:18 AM, wrote:

    Hi

    I'm trying to understand ranging over channels. In the Golang spec it says:

    For channels, the iteration values produced are the successive values
    sent on the channel until the channel is closed. If the channel is nil, the
    range expression blocks forever.

    For closing, the reference says:

    For a channel c, the built-in function close(c) records that no more
    values will be sent on the channel.

    And there are plenty of examples that invoke close() explicitly. But I am
    also seeing from time to time examples that don't explicitly call close.
    Here is one from
    http://golangtutorials.blogspot.com/2011/06/channels-in-go-range-and-select.html

    package main

    import (
    "fmt"
    "time"
    "strconv"
    )

    func makeCakeAndSend(cs chan string, count int) {
    for i := 1; i <= count; i++ {
    cakeName := "Strawberry Cake " + strconv.Itoa(i)
    cs <- cakeName //send a strawberry cake
    }
    }

    func receiveCakeAndPack(cs chan string) {
    for s := range cs {
    fmt.Println("Packing received cake: ", s)
    }
    }

    func main() {
    cs := make(chan string)
    go makeCakeAndSend(cs, 5)
    go receiveCakeAndPack(cs)

    //sleep for a while so that the program doesn’t exit immediately
    time.Sleep(3 * 1e9)
    }

    This code doesn't call close(). So how does it work? Does ranging over
    channels just run until there are no more messages left on the channel? And
    then messages that come in after it happened to be drained simply have to
    wait for the next send? If so, why does the documentation mention that
    ranging works until a channel is closed? Or is that channel actually closed?




    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Paul Borman at May 13, 2016 at 5:28 pm
    Why do you think receiveCakeAndPack is exiting (i.e., the range
    completes)? As Chris mentions, it isn't returning.
    On Fri, May 13, 2016 at 10:18 AM, wrote:

    Hi

    I'm trying to understand ranging over channels. In the Golang spec it says:

    For channels, the iteration values produced are the successive values
    sent on the channel until the channel is closed. If the channel is nil, the
    range expression blocks forever.

    For closing, the reference says:

    For a channel c, the built-in function close(c) records that no more
    values will be sent on the channel.

    And there are plenty of examples that invoke close() explicitly. But I am
    also seeing from time to time examples that don't explicitly call close.
    Here is one from
    http://golangtutorials.blogspot.com/2011/06/channels-in-go-range-and-select.html

    package main

    import (
    "fmt"
    "time"
    "strconv"
    )

    func makeCakeAndSend(cs chan string, count int) {
    for i := 1; i <= count; i++ {
    cakeName := "Strawberry Cake " + strconv.Itoa(i)
    cs <- cakeName //send a strawberry cake
    }
    }

    func receiveCakeAndPack(cs chan string) {
    for s := range cs {
    fmt.Println("Packing received cake: ", s)
    }
    }

    func main() {
    cs := make(chan string)
    go makeCakeAndSend(cs, 5)
    go receiveCakeAndPack(cs)

    //sleep for a while so that the program doesn’t exit immediately
    time.Sleep(3 * 1e9)
    }

    This code doesn't call close(). So how does it work? Does ranging over
    channels just run until there are no more messages left on the channel? And
    then messages that come in after it happened to be drained simply have to
    wait for the next send? If so, why does the documentation mention that
    ranging works until a channel is closed? Or is that channel actually closed?




    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Ray Toal at May 13, 2016 at 5:43 pm
    I know! I always use close explicitly. But I sometimes see posts where this
    is not done. I just wanted to make sure I wasn't missing anything.

    Just wanted clarification. I guess this is a common bug.

    On Friday, May 13, 2016 at 10:28:51 AM UTC-7, Paul Borman wrote:

    Why do you think receiveCakeAndPack is exiting (i.e., the range
    completes)? As Chris mentions, it isn't returning.
    On Fri, May 13, 2016 at 10:18 AM, <ray....@gmail.com <javascript:>> wrote:

    Hi

    I'm trying to understand ranging over channels. In the Golang spec it
    says:

    For channels, the iteration values produced are the successive values
    sent on the channel until the channel is closed. If the channel is nil, the
    range expression blocks forever.

    For closing, the reference says:

    For a channel c, the built-in function close(c) records that no more
    values will be sent on the channel.

    And there are plenty of examples that invoke close() explicitly. But I am
    also seeing from time to time examples that don't explicitly call close.
    Here is one from
    http://golangtutorials.blogspot.com/2011/06/channels-in-go-range-and-select.html

    package main

    import (
    "fmt"
    "time"
    "strconv"
    )

    func makeCakeAndSend(cs chan string, count int) {
    for i := 1; i <= count; i++ {
    cakeName := "Strawberry Cake " + strconv.Itoa(i)
    cs <- cakeName //send a strawberry cake
    }
    }

    func receiveCakeAndPack(cs chan string) {
    for s := range cs {
    fmt.Println("Packing received cake: ", s)
    }
    }

    func main() {
    cs := make(chan string)
    go makeCakeAndSend(cs, 5)
    go receiveCakeAndPack(cs)

    //sleep for a while so that the program doesn’t exit immediately
    time.Sleep(3 * 1e9)
    }

    This code doesn't call close(). So how does it work? Does ranging over
    channels just run until there are no more messages left on the channel? And
    then messages that come in after it happened to be drained simply have to
    wait for the next send? If so, why does the documentation mention that
    ranging works until a channel is closed? Or is that channel actually closed?




    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts...@googlegroups.com <javascript:>.
    For more options, visit https://groups.google.com/d/optout.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Paul Borman at May 13, 2016 at 5:48 pm
    receiveCakeAndPack does not exit, nor does the range complete. It displays
    the 5 cakes and then waits for more. After three seconds your program
    exists and receiveCakeAndPack, along with the rest of your program,
    vanishes.

    Try putting a fmt.Println *after* the range and see what happens. The put
    a close(ch) at the end of makeCakeAndSend and see what happens.

         -Paul
    On Fri, May 13, 2016 at 10:43 AM, wrote:

    I know! I always use close explicitly. But I sometimes see posts where
    this is not done. I just wanted to make sure I wasn't missing anything.

    Just wanted clarification. I guess this is a common bug.

    On Friday, May 13, 2016 at 10:28:51 AM UTC-7, Paul Borman wrote:

    Why do you think receiveCakeAndPack is exiting (i.e., the range
    completes)? As Chris mentions, it isn't returning.
    On Fri, May 13, 2016 at 10:18 AM, wrote:

    Hi

    I'm trying to understand ranging over channels. In the Golang spec it
    says:

    For channels, the iteration values produced are the successive
    values sent on the channel until the channel is closed. If the channel is
    nil, the range expression blocks forever.

    For closing, the reference says:

    For a channel c, the built-in function close(c) records that no more
    values will be sent on the channel.

    And there are plenty of examples that invoke close() explicitly. But I
    am also seeing from time to time examples that don't explicitly call close.
    Here is one from
    http://golangtutorials.blogspot.com/2011/06/channels-in-go-range-and-select.html

    package main

    import (
    "fmt"
    "time"
    "strconv"
    )

    func makeCakeAndSend(cs chan string, count int) {
    for i := 1; i <= count; i++ {
    cakeName := "Strawberry Cake " + strconv.Itoa(i)
    cs <- cakeName //send a strawberry cake
    }
    }

    func receiveCakeAndPack(cs chan string) {
    for s := range cs {
    fmt.Println("Packing received cake: ", s)
    }
    }

    func main() {
    cs := make(chan string)
    go makeCakeAndSend(cs, 5)
    go receiveCakeAndPack(cs)

    //sleep for a while so that the program doesn’t exit immediately
    time.Sleep(3 * 1e9)
    }

    This code doesn't call close(). So how does it work? Does ranging over
    channels just run until there are no more messages left on the channel? And
    then messages that come in after it happened to be drained simply have to
    wait for the next send? If so, why does the documentation mention that
    ranging works until a channel is closed? Or is that channel actually closed?




    --
    You received this message because you are subscribed to the Google
    Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send
    an email to golang-nuts...@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Ray Toal at May 13, 2016 at 5:59 pm
    Ahhhh, great advice! That *really* helps.

    I've never liked that style of doing a sleep in main to "let things happen"
    but I guess for small examples it's convenient.

    I like it when the generators are goroutines and they explicitly close,
    while the main thread uses the range to read.

    Now that you mention it, it's very obvious that the execution is blocked
    within the for loop. Duh.
    On Friday, May 13, 2016 at 10:48:51 AM UTC-7, Paul Borman wrote:

    receiveCakeAndPack does not exit, nor does the range complete. It
    displays the 5 cakes and then waits for more. After three seconds your
    program exists and receiveCakeAndPack, along with the rest of your program,
    vanishes.

    Try putting a fmt.Println *after* the range and see what happens. The
    put a close(ch) at the end of makeCakeAndSend and see what happens.

    -Paul
    On Fri, May 13, 2016 at 10:43 AM, <ray....@gmail.com <javascript:>> wrote:

    I know! I always use close explicitly. But I sometimes see posts where
    this is not done. I just wanted to make sure I wasn't missing anything.

    Just wanted clarification. I guess this is a common bug.

    On Friday, May 13, 2016 at 10:28:51 AM UTC-7, Paul Borman wrote:

    Why do you think receiveCakeAndPack is exiting (i.e., the range
    completes)? As Chris mentions, it isn't returning.
    On Fri, May 13, 2016 at 10:18 AM, wrote:

    Hi

    I'm trying to understand ranging over channels. In the Golang spec it
    says:

    For channels, the iteration values produced are the successive
    values sent on the channel until the channel is closed. If the channel is
    nil, the range expression blocks forever.

    For closing, the reference says:

    For a channel c, the built-in function close(c) records that no
    more values will be sent on the channel.

    And there are plenty of examples that invoke close() explicitly. But I
    am also seeing from time to time examples that don't explicitly call close.
    Here is one from
    http://golangtutorials.blogspot.com/2011/06/channels-in-go-range-and-select.html

    package main

    import (
    "fmt"
    "time"
    "strconv"
    )

    func makeCakeAndSend(cs chan string, count int) {
    for i := 1; i <= count; i++ {
    cakeName := "Strawberry Cake " + strconv.Itoa(i)
    cs <- cakeName //send a strawberry cake
    }
    }

    func receiveCakeAndPack(cs chan string) {
    for s := range cs {
    fmt.Println("Packing received cake: ", s)
    }
    }

    func main() {
    cs := make(chan string)
    go makeCakeAndSend(cs, 5)
    go receiveCakeAndPack(cs)

    //sleep for a while so that the program doesn’t exit immediately
    time.Sleep(3 * 1e9)
    }

    This code doesn't call close(). So how does it work? Does ranging over
    channels just run until there are no more messages left on the channel? And
    then messages that come in after it happened to be drained simply have to
    wait for the next send? If so, why does the documentation mention that
    ranging works until a channel is closed? Or is that channel actually closed?




    --
    You received this message because you are subscribed to the Google
    Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send
    an email to golang-nuts...@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts...@googlegroups.com <javascript:>.
    For more options, visit https://groups.google.com/d/optout.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedMay 13, '16 at 5:18p
activeMay 13, '16 at 5:59p
posts6
users3
websitegolang.org

People

Translate

site design / logo © 2022 Grokbase