Go for Python users
Pyvo, 15. 7. 2020
What?
Why?
Why not?
Contra Python
Sum ints in a file
func sumInts(filename string) (int, error) {
f, err := os.Open(filename)
if err != nil {
return 0, err
}
defer f.Close()
scanner := bufio.NewScanner(f)
sum := 0
for scanner.Scan() {
num, err := strconv.Atoi(scanner.Text())
if err != nil {
return 0, err
}
sum += num
}
if scanner.Err() != nil {
return 0, scanner.Err()
}
return sum, nil
}
Run it on some files
func run() error {
filenames, err := filepath.Glob("data/*.txt")
if err != nil {
return err
}
for _, filename := range filenames {
sum, err := sumInts(filename)
if err != nil {
return err
}
fmt.Println(sum)
}
return nil
}
Run it concurrently
func run() error {
filenames, err := filepath.Glob("data/*.txt")
if err != nil {
return err
}
for _, filename := range filenames {
go func(filename string) {
sum, err := sumInts(filename)
if err != nil {
panic(err)
}
fmt.Println(sum)
}(filename)
}
return nil
}
Run it concurrently and wait for it
var wg sync.WaitGroup
wg.Add(len(filenames))
for _, filename := range filenames {
go func(filename string) {
defer wg.Done()
sum, err := sumInts(filename)
if err != nil {
panic(err)
}
fmt.Println(sum)
}(filename)
}
wg.Wait()
Communicate instead of waiting
results := make(chan int)
for _, filename := range filenames {
go func(filename string) {
sum, err := sumInts(filename)
if err != nil {
panic(err)
}
results <- sum
}(filename)
}
for j := 0; j < len(filenames); j++ {
fmt.Println(<-results)
}
Launch workers and subscribe to work
nworkers := 2
work := make(chan string) // filenames
results := make(chan int)
for j := 0; j < nworkers; j++ {
go func() {
for filename := range work {
sum, err := sumInts(filename)
if err != nil {
panic(err)
}
results <- sum
}
}()
}
Send the work and receive results
done := make(chan bool)
go func() {
for j := 0; j < len(filenames); j++ {
fmt.Println(<-results)
}
close(results)
close(work)
done <- true
}()
for _, filename := range filenames {
work <- filename
}
<-done
Thank you