Scanf in several larynx gives unexpected results

I was just experimenting in the golang. I came across an interesting result. This is my code.

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    var str1, str2 string
    wg.Add(2)
    go func() {
        fmt.Scanf("%s", &str1)
        wg.Done()
    }()
    go func() {
        fmt.Scanf("%s", &str2)
        wg.Done()
    }()
    wg.Wait()
    fmt.Printf("%s %s\n", str1, str2)
}

I gave the following input.

beat
it

I expected the result to be either

it beat

or

beat it

But I get it.

eat bit

Can someone help me understand why this is so?

+4
source share
2 answers

fmt.Scanfnot an atomic operation. Here's the implementation: http://golang.org/src/pkg/fmt/scan.go#L1115

There is no semaphore that prevents two parallel executions. So it just happens that the executions are really parallel, and since there is no buffering there, any reading of bytes is an I / O operation and thus the ideal time for the go scheduler to change goroutine.

+4

, ( stdin) goroutines.

. i.e:

  • first goroutine 1 stdin, goroutine 2
  • goroutine 2 stdin, goroutine 1
  • goroutine 1 , goroutine 2, char, goroutine 1
  • ... .. ...

goroutine , , .

:

package main

import (
    "fmt"
    "io"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    words := make(chan string, 10)
    wg.Add(1)
    go func() {
        for {
            var buff string
            _, err := fmt.Scanf("%s", &buff)
            if err != nil {
                if err != io.EOF {
                    fmt.Println("Error: ", err)
                }
                break
            }
            words <- buff
        }
        close(words)
        wg.Done()
    }()
    // Multiple consumers
    for i := 0; i < 5; i += 1 {
        go func() {
            for word := range words {
                fmt.Printf("%s\n", word)
            }
        }()
    }
    wg.Wait()
}
+3

Source: https://habr.com/ru/post/1542292/


All Articles