go does not work with for

473 views
Skip to first unread message

Xan

unread,
Jan 6, 2013, 2:43:45 PM1/6/13
to golan...@googlegroups.com
Hi,

I have a trouble with this code:

package main

import "fmt"

func print(i int, valor string) {

    fmt.Printf("position: %d element: %s \n", i, valor)
}

func main() {

    urls := []string{"1", "2", "3", "4", "5"}
    for k, v := range urls {
        go print(k, v)
    }
}


It does not print nothing. If I quit "go", then all is fine.
What's trouble. go and gccgo don't show me any compilation error.

Thanks in advance,
Xan,

Patrick Mylund Nielsen

unread,
Jan 6, 2013, 2:47:10 PM1/6/13
to Xan, golang-nuts

Patrick Mylund Nielsen

unread,
Jan 6, 2013, 2:48:29 PM1/6/13
to Xan, golang-nuts
Sorry, that's one of the problems. The other problem is that the program exits when main does. Add "select {}" below the for loop to make the main goroutine wait forever, or add e.g. time.Sleep(5 * time.Second)

Kevin Malachowski

unread,
Jan 6, 2013, 2:49:49 PM1/6/13
to golan...@googlegroups.com
What could be happening is that func main is exiting before any goroutine starts to execute. When "main" exits all goroutines are immediately terminated and the program finishes. Try having a sleep call right after the for loop.

Patrick Mylund Nielsen

unread,
Jan 6, 2013, 2:50:17 PM1/6/13
to Xan, golang-nuts
Eugh. Sorry for the confusion. I skimmed your code a little too quickly. Disregard my first email :)

David DENG

unread,
Jan 6, 2013, 7:34:22 PM1/6/13
to golan...@googlegroups.com
You need to read this carefully:


David

Skip Tavakkolian

unread,
Jan 6, 2013, 9:57:46 PM1/6/13
to Xan, golan...@googlegroups.com
main is exiting before other routines can finish; here's one way to
coordinate for main to wait for all routines to finish:

http://play.golang.org/p/dyOSX_Vj1n
> --
>
>

xancorreu

unread,
Jan 7, 2013, 1:40:12 PM1/7/13
to Skip Tavakkolian, golan...@googlegroups.com
Mmm... thanks. But it's an annoying thing: we have to run "artifial
code" for waiting goroutines... It's suppossed that we don't want to
wait because we use goroutines ;-)

Is there any way of waiting **minimum** time?

Thanks,
Xan.

Al 07/01/13 03:57, En/na Skip Tavakkolian ha escrit:

Patrick Mylund Nielsen

unread,
Jan 7, 2013, 1:39:05 PM1/7/13
to xancorreu, Skip Tavakkolian, golang-nuts
time.Sleep


--



Cole Mickens

unread,
Jan 7, 2013, 3:05:39 PM1/7/13
to golan...@googlegroups.com, Skip Tavakkolian
You can use a waitgroup to avoid sleeping for a semi-random amount of time: http://golang.org/pkg/sync/#WaitGroup (check the example)

Nate Finch

unread,
Jan 7, 2013, 6:22:21 PM1/7/13
to golan...@googlegroups.com, Skip Tavakkolian
You'll need to write some way for each goroutine to signal the main goroutine that it's done (probably writing to a channel that main listens on).  As far as I know, there's no real way to simply say "wait until all other goroutines are done". 

Cole Mickens

unread,
Jan 7, 2013, 6:55:15 PM1/7/13
to golan...@googlegroups.com, Skip Tavakkolian
To further my comment and others', here are a pair of examples:

using channels: http://play.golang.org/p/IY7WwDTesM

The other example using channels uses an unbuffered channel so it will actually block the sending to the done channel until it is received with the for loop at the end. It makes no difference in this case, but if the function were less trivial then it may matter whether you want to block or not.


On Monday, January 7, 2013 12:40:12 PM UTC-6, Xan wrote:

Phil Whelan

unread,
Jan 7, 2013, 7:37:12 PM1/7/13
to Cole Mickens, golan...@googlegroups.com
On Mon, Jan 7, 2013 at 12:05 PM, Cole Mickens <cole.m...@gmail.com> wrote:
>
> You can use a waitgroup to avoid sleeping for a semi-random amount of time: http://golang.org/pkg/sync/#WaitGroup (check the example)

Since calling "go" and "wg.Add" is not atomic, there might be a
potential race condition that causes..

panic: sync: negative WaitGroup counter

...if wg.Done() gets called before wg.Add()

Maybe calling wg.Add() before your goroutine would be better?

Phil

Xan

unread,
Jan 8, 2013, 8:07:25 AM1/8/13
to golan...@googlegroups.com, Cole Mickens, ph...@fluidfeatures.com
Thanks Cole and Phil. This is what I want: routines without having to re-show the entire table.

Phil, do you think this [http://play.golang.org/p/AB_w3XcsQL] is better than the previous version?

Thanks,
Xan.

Phil Whelan

unread,
Jan 8, 2013, 1:47:09 PM1/8/13
to Xan, golan...@googlegroups.com, Cole Mickens
On Tue, Jan 8, 2013 at 5:07 AM, Xan <xanc...@gmail.com> wrote: 
Phil, do you think this [http://play.golang.org/p/AB_w3XcsQL] is better than the previous version?

Looks good to me. Although, I'm very fresh to Go, so Cole might have a better idea on the intricacies of Go.

Sean Russell

unread,
Jan 8, 2013, 9:15:04 PM1/8/13
to golan...@googlegroups.com, Cole Mickens, ph...@fluidfeatures.com
On Tuesday, January 8, 2013 8:07:25 AM UTC-5, Xan wrote:
Thanks Cole and Phil. This is what I want: routines without having to re-show the entire table.

Phil, do you think this [http://play.golang.org/p/AB_w3XcsQL] is better than the previous version?

I often use this pattern:


It prevents both global variables as well as having to pollute called routines with synchronization issues.  You can factor out the lambda expression for readability or optimization.

--- SER

Sonia Keys

unread,
Jan 9, 2013, 1:26:48 PM1/9/13
to golan...@googlegroups.com, Cole Mickens, ph...@fluidfeatures.com
I like the style of Sean's program.

Let me fix one subtle problem though.  Printing through the fmt package is not typically thread safe at the operating system level.  If the runtime actually puts your separate goroutines on separate OS threads, you risk garbled output--probably only very rarely, but it's still a bug.

A solution is to serialize access to os.Stdout, and the log package can do that.  Here (playground) is one way.  By assigning the the package name "fmt" to the log package, I kind of put up a road block warning against use of the real fmt package.  Feel free to take down the road block, but be aware that adding other unserialized output to os.Stdout can ruin this attempt to keep output serialized.  At some point as your program grows, you probably won't want to leave your serialized calls writing to os.Stdout, much less qualified with "fmt."

bryanturley

unread,
Jan 9, 2013, 1:44:29 PM1/9/13
to golan...@googlegroups.com, Cole Mickens, ph...@fluidfeatures.com


On Wednesday, January 9, 2013 12:26:48 PM UTC-6, Sonia Keys wrote:
I like the style of Sean's program.

Let me fix one subtle problem though.  Printing through the fmt package is not typically thread safe at the operating system level.  If the runtime actually puts your separate goroutines on separate OS threads, you risk garbled output--probably only very rarely, but it's still a bug.


It is thread safe, it just writes in chunks and with multiple writers you often get the garbled output you are noticing.

A solution is to serialize access to os.Stdout, and the log package can do that.  Here (playground) is one way.  By assigning the the package name "fmt" to the log package, I kind of put up a road block warning against use of the real fmt package.  Feel free to take down the road block, but be aware that adding other unserialized output to os.Stdout can ruin this attempt to keep output serialized.  At some point as your program grows, you probably won't want to leave your serialized calls writing to os.Stdout, much less qualified with "fmt."


Real fmt is useful for things other than fmt.PrintX()  for instance fmt.Sprintf(), I wouldn't include log renamed to fmt just use log and/or fmt.
Reply all
Reply to author
Forward
0 new messages