Go Channels Help

Hi all,
I am trying try to learn channels and when I ran the code I get following output which uppercase after the first run. in playground I get all lowercase. running v1.10
thanks in advance

google
ALTAVISTA
ALPHABET
BING
YAHOO
func main() {
	names := []string{
		"yahoo", "google", "altavista", "alphabet", "bing",
	}

	n := make(chan string, len(names))


	for _, name := range names {
		n <- name
		go ToUpper(n)
	}

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

	close(n)
}

func ToUpper(c chan string) {

	u := strings.ToUpper(<-c)
	c <- u
}

You do not wait for goroutines to finish. Better play with unbuffered channels and use waitgroups. The simplest but not good solution would be to add some sleep at the end of main().

One more thing, use channels just to read or write, not both.

thanks

Use separate channels for the input and for the result.

In your code, the ToUpper goroutines and the fmt.Println loop in the main goroutine read from the same channel that contains both the input and the output of ToUpper(). There is no defined sequence in which the goroutines run, so the result is undetermined.

The playground runs the fmt.Println loop first, which is why you get the unprocessed input as output. When the ToUpper goroutines run, the channel is already empty. (Apart from that, when the main goroutine ends, all other goroutines are stopped immediately, so the ToUpper goroutines may never run.)

On your local machine, the fmt.Println() loop seems to run at least once before the first ToUpper goroutine starts, which is why you see the first ouput unprocessed.

Using separate channels for input and result values should fix the issue. And ensure to let the main goroutine wait for the other goroutines to finish. (See e.g. sync/WaitGroup.)

1 Like

Check this example

thank you all for the inputs
I have resolved question with this example.

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
)

func getLength(url string) (int, error) {
	resp, err := http.Get(url)
	if err != nil {
		return 0, nil
	}
	defer resp.Body.Close()

	pageByte, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return 0, nil
	}

	return len(pageByte), nil

}

func worker(urlCh, sizeCh chan string, id int) {
	for {
		url := <-urlCh
		psize, err := getLength(url)
		if err != nil {
			os.Exit(1)
		}
		sizeCh <- fmt.Sprintf("%s length is %d (%d)", url, psize, id)
	}
}

func generator(url string, urlCh chan string) {
	urlCh <- url
}

func main() {
	// url := "http://www.google.ca"
	urls := []string{"http://www.golang.org", "http://www.google.ca",
		"http://www.bing.com", "http://www.yahoo.ca", "http://www.toronto.ca"}

	sizeCh := make(chan string)
	urlCh := make(chan string)

	for i := 0; i < 10; i++ {
		go worker(urlCh, sizeCh, i)
	}

	for _, url := range urls {
		go generator(url, urlCh)
	}

	for i := 0; i < len(urls); i++ {
		fmt.Printf("%s\n", <-sizeCh)
	}
}

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.