Golang program hangs without finishing execution

Issue

I have the following golang program;

package main

import (
    "fmt"
    "net/http"
    "time"
)

var urls = []string{
    "http://www.google.com/",
    "http://golang.org/",
    "http://yahoo.com/",
}

type HttpResponse struct {
    url      string
    response *http.Response
    err      error
    status   string
}

func asyncHttpGets(url string, ch chan *HttpResponse) {
    client := http.Client{}
    if url == "http://www.google.com/" {
        time.Sleep(500 * time.Millisecond) //google is down
    }

    fmt.Printf("Fetching %s \n", url)
    resp, err := client.Get(url)
    u := &HttpResponse{url, resp, err, "fetched"}
    ch <- u
    fmt.Println("sent to chan")
}

func main() {
    fmt.Println("start")
    ch := make(chan *HttpResponse, len(urls))
    for _, url := range urls {
        go asyncHttpGets(url, ch)
    }

    for i := range ch {
        fmt.Println(i)
    }
    fmt.Println("Im done")

}

Run it on Playground

However when I run it; it hangs (ie the last part that ought to print Im done doesnt run.)
Here’s the terminal output;;
$ go run get.go
start
Fetching http://yahoo.com/
Fetching http://golang.org/
Fetching http://www.google.com/
sent to chan
&{http://www.google.com/ 0xc820144120 fetched}
sent to chan
&{http://golang.org/ 0xc82008b710 fetched}
sent to chan
&{http://yahoo.com/ 0xc82008b7a0 fetched}

Solution

The problem is that ranging over a channel in a for loop will continue forever unless the channel is closed. If you want to read precisely len(urls) values from the channel, you should loop that many times:

for i := 0; i < len(urls); i++ {
    fmt.Println(<-ch)
}

Answered By – joshlf

Answer Checked By – Gilberto Lyons (GoLangFix Admin)

Leave a Reply

Your email address will not be published.