Skip to content

Instantly share code, notes, and snippets.

@vporoshok
Last active September 10, 2019 04:54
Show Gist options
  • Save vporoshok/c4706e31437d9ed683daa9a34c6ab469 to your computer and use it in GitHub Desktop.
Save vporoshok/c4706e31437d9ed683daa9a34c6ab469 to your computer and use it in GitHub Desktop.
Semaphore on channel
package main
import (
"bufio"
"flag"
"fmt"
"io/ioutil"
"net/http"
"os"
"strings"
"sync"
"sync/atomic"
)
func main() {
parallelism := flag.Int("n", 4, "Number of go-routines")
flag.Parse()
if *parallelism < 1 {
fmt.Fprintf(os.Stderr, "invalid parallelism number %d, should be a positive number", *parallelism)
os.Exit(2)
}
err := work(*parallelism)
if err != nil {
fmt.Fprintf(os.Stderr, "%+v", err)
os.Exit(1)
}
}
func work(parallelism int) error {
semaphore := make(chan struct{}, parallelism)
wg := new(sync.WaitGroup)
scanner := bufio.NewScanner(os.Stdin)
var total int64
for scanner.Scan() {
if err := scanner.Err(); err != nil {
return err
}
line := scanner.Text()
semaphore <- struct{}{}
wg.Add(1)
go func() {
n, err := processURL(line)
if err != nil {
fmt.Fprintf(os.Stderr, "Error occurred on loading %s: %+v\n", line, err)
}
fmt.Printf("Count for %s: %d\n", line, n)
atomic.AddInt64(&total, int64(n))
<-semaphore
wg.Done()
}()
}
wg.Wait()
fmt.Printf("Total: %d\n", total)
return nil
}
func processURL(url string) (int, error) {
res, err := http.Get(url)
if err != nil {
return 0, err
}
defer func() {
_ = res.Body.Close()
}()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return 0, err
}
return strings.Count(string(body), "Go"), nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment