Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple method for limiting concurrency in Go

Tags:

go

goroutine

I have a CSV file with ~10k URLs I need to HTTP get. What is the simplest way to limit the concurrency of Go routines to no more than 16 at a time?

func getUrl(url string) {
    request := gorequest.New()
    resp, body, errs := request.Get(each[1]).End()
    _ = resp
    _ = body
    _ = errs
}

func main() {

    csvfile, err := os.Open("urls.csv")
    defer csvfile.Close()
    reader := csv.NewReader(csvfile)
    reader.FieldsPerRecord = -1 
    rawCSVdata, err := reader.ReadAll()

    completed := 0
    for _, each := range rawCSVdata {
        go getUrl(each[1])
        completed++
    }
}
like image 516
ewhitt Avatar asked Nov 01 '15 09:11

ewhitt


People also ask

How does Go handle concurrency?

In Go, concurrency works through the use of in-built functions known as Goroutines. Goroutines are functions, unique to Go, that run at the same time alongside other code or programs. They're not OS threads, though, they may be considered lightweight threads.

Is Golang good for concurrency?

Concurrency in Golang is cheap and easy. Goroutines are cheap, lightweight threads. Channels, are the conduits that allow for communication between goroutines. Communicating Sequential Processes, or CSP for short, is used to describe how systems that feature multiple concurrent models should interact with one another.

How do you get concurrency in Golang?

The key to achieving Golang concurrency is using Goroutines – lightweight, low-cost methods or functions that can run concurrently with other methods and functions.

Which concurrency model does Golang use?

Following a model proposed by the renowned computer scientist Tony Hoare, Go uses the concurrency model called Communicating Sequential Processes (CSP).


1 Answers

A producer-consumers pattern:

package main

import (
    "encoding/csv"
    "os"
    "sync"

    "github.com/parnurzeal/gorequest"
)

const workersCount = 16

func getUrlWorker(urlChan chan string) {
    for url := range urlChan {
        request := gorequest.New()
        resp, body, errs := request.Get(url).End()
        _ = resp
        _ = body
        _ = errs
    }
}

func main() {
    csvfile, err := os.Open("urls.csv")
    if err != nil {
        panic(err)
    }
    defer csvfile.Close()

    reader := csv.NewReader(csvfile)
    reader.FieldsPerRecord = -1
    rawCSVdata, err := reader.ReadAll()

    var wg sync.WaitGroup
    urlChan := make(chan string)

    wg.Add(workersCount)

    for i := 0; i < workersCount; i++ {
        go func() {
            getUrlWorker(urlChan)
            wg.Done()
        }()
    }

    completed := 0
    for _, each := range rawCSVdata {
        urlChan <- each[1]
        completed++
    }
    close(urlChan)

    wg.Wait()
}
like image 162
HectorJ Avatar answered Oct 26 '22 04:10

HectorJ