Reading multiple return values ​​from goroutine

PHPz
Release: 2024-02-09 12:30:09
forward
1054 people have browsed it

从 goroutine 读取多个返回值

php Editor Apple Reading multiple return values ​​from goroutine is a common operation in the Go language. Goroutine is a lightweight thread in the Go language that can achieve concurrent execution. In some cases, we need to get the return value from one or more goroutines for further processing. This operation can be achieved by using channels, which are an important mechanism for communication between goroutines. Through channels, we can pass data between goroutines and achieve synchronization and communication between coroutines. In this article, we will detail the tips and considerations on how to read multiple return values ​​from a goroutine.

Question content

I'm trying to write wc(1) in Go, and I'm trying to use goroutines to compute a large number of input files more efficiently. My code works fine, but I'm having trouble implementing a way to summarize statistics for all go routines. How can I pass the function variables nl, nw, nc to main and aggregate them there after all the go routines have finished their work?

package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
)

func main() {
    ch := make(chan string)

    for _, arg := range os.Args[1:] {
        go wc(arg, ch)
    }
    for range os.Args[1:] {
        fmt.Println(<-ch)
    }
    // Todo: summarize results...
}

func wc(arg string, ch chan<- string) {
    nl, nw, nc := 0, 0, 0

    file, err := os.Open(arg)
    if err != nil {
        fmt.Println("Can't open file: %v", err)
    }
    defer file.Close()

    scan := bufio.NewScanner(file)
    for scan.Scan() {
        nl++

        line := scan.Text()
        words := bufio.NewScanner(strings.NewReader(line))
        words.Split(bufio.ScanWords)
        for words.Scan() {
            nw++
        }

        runes := bufio.NewReader(strings.NewReader(line))
        for {
            if _, _, err := runes.ReadRune(); err != nil {
                break
            } else {
                nc++
            }
        }
    }

    ch <- fmt.Sprintf("%8d%8d%8d", nl, nw, nc+nl)
}
Copy after login

Solution

You are close to the answer! I'd suggest a quick refactor to return a Result object with numbers, which would allow adding them at the end easily (instead of using a string). Therefore, you can use chan result instead of chan string.

Basically, you can introduce a totalResult variable and when iterating over all results, just add nl, nc and nw# The result of ## is added to this total variable.

<code>package main

import (
    "fmt"
    "math/rand"
)

// define a struct to hold the result
type Result struct {
    nl int
    nw int
    nc int
}

// this is to be able to use fmt.Println(result)
func (r Result) String() string {
    return fmt.Sprintf("%8d%8d%8d", r.nl, r.nw, r.nc+r.nl)
}

func main() {
    ch := make(chan Result)

    for _, arg := range os.Args[1:] {
        go wc(arg, ch)
    }

    totalResult := Result{}

    for range os.Args[1:] {
        result := <-ch
        fmt.Println(result) // just for debugging

        // sum everything
        totalResult.nl += result.nl
        totalResult.nw += result.nw
        totalResult.nc += result.nc
    }

    fmt.Println("Total result:")
    fmt.Println(totalResult)
}

func wc(arg string, ch chan<- Result) {
    nl, nw, nc := 0, 0, 0

    // your logic to compute nl, nw, nc goes here

    ch <- Result{nl: nl, nw: nw, nc: nc + nl}
}
</code>
Copy after login

You should get something like this (containing 3 files):

37      50    4753
      19     106     821
      47     255    3806
Total result:
     103     411    9380
Copy after login

The above is the detailed content of Reading multiple return values ​​from goroutine. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!