Skip to content

Latest commit

 

History

History

barrier

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

Concurrency » Barrier

Description

The purpose of this pattern is to collect all the results from different functions and goroutines before pass.

Implementation

In this implementation we'll GET some urls (often used for testing purpose). According to pattern description we will output somethine just after both request have been received a response.

func main() {
	barrier(
		"http://httpbin.org/headers",
		"http://httpbin.org/user-agent",
	)
}

This implementation is very idiomatic and uses go keyword. This keyword will start new gorouting with function makeRequest. Also, this function contains a channel called in.

func barrier(urls ...string) {
	numOfRequsts := len(urls)

	in := make(chan Response, numOfRequsts)
	defer close(in)

	responses := make([]Response, numOfRequsts)

	for _, uri := range urls {
		go makeRequest(
			in,
			uri,
		)
	}

  // …
}

Instead, makeRequest function get the content, makes a covertion to string and return to channel everythin.

func makeRequest(out chan<- Response, url string) {
	// …

	resp, err := client.Get(url)
	byt, err := ioutil.ReadAll(resp.Body)
	res.Resp = string(byt)
	out <- res

	// …
}

Here the complete solution:

var timeout int = 5000

type Response struct {
	Err  error
	Resp string
}

func barrier(urls ...string) {
	numOfRequsts := len(urls)

	in := make(chan Response, numOfRequsts)
	defer close(in)

	responses := make([]Response, numOfRequsts)

	for _, uri := range urls {
		go makeRequest(
			in,
			uri,
		)
	}

	var hasError bool
	for i := 0; i < numOfRequsts; i++ {
		resp := <-in
		if resp.Err != nil {
			fmt.Println("ERROR: ", resp.Err)
			hasError = true
		}
		responses[i] = resp
	}

	if !hasError {
		for _, resp := range responses {
			fmt.Println(resp.Resp)
		}
	}
}

func makeRequest(out chan<- Response, url string) {
	res := Response{}
	client := http.Client{
		Timeout: time.Duration(time.Duration(timeout) * time.Millisecond),
	}

	resp, err := client.Get(url)
	if err != nil {
		res.Err = err
		out <- res
		return
	}

	byt, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		res.Err = err
		out <- res
		return
	}

	res.Resp = string(byt)
	out <- res
}

func main() {
	barrier(
		"http://httpbin.org/headers",
		"http://httpbin.org/user-agent",
	)
}