在Go

时间:2017-10-14 13:02:13

标签: go concurrency

所以我有一个这样的文件:

NAME : a280
COMMENT : drilling problem (Ludwig)
TYPE : TSP
DIMENSION: 280
EDGE_WEIGHT_TYPE : EUC_2D
NODE_COORD_SECTION
  1 288 149
  2 288 129
  3 270 133
  4 256 141
  5 256 157
  6 246 157
  7 236 169
  8 228 169
  9 228 161
 10 220 169
 11 212 169
 12 204 169
 13 196 169
 14 188 169
 15 196 161

依旧......

这些数字是城市解决TSP的线索。我想在Golang写这个。现在这些实例可能像200个城市,甚至是40,000个城市。我想获得最好的解决方案,所以我认为我应该同时处理这个文件。我有以下代码:

package main

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

func getCords(queue chan string) {
    cords := regexp.MustCompile(`\s*\d+\s+\d+\s+\d+`)
    for line := range queue {
        if cords.MatchString(line) {
            fmt.Println(line)
        }
    }
}

func readFile(fileName string) {
    cords := make(chan string)
    file := strings.NewReader(fileName)
    go func() {
        scanner := bufio.NewScanner(file)
        for scanner.Scan() {
            cords <- scanner.Text()
        }
        close(cords)
    }()
}

// Menu - main program menu
func Menu() {
    reader := bufio.NewReader(os.Stdin)
    fmt.Println("==================    Projektowanie efektywnych algorytmów    ==================")
    fmt.Println("==================    Zadanie nr 1 - Algorytm xyz             ==================")
    // Wczytywanie pliku z danymi
    // Format: Lp. X Y
    fmt.Printf("\nPodaj nazwę pliku: ")
    fileName, err := reader.ReadString('\n')
    if err != nil {
        fmt.Println(err)
        return
    }
    readFile(fileName)
}

func main() {
    Menu()
}

在函数getCords中我需要使用regex,因为文件往往在开头就有信息部分。

问题始于readFile()。我启动了一个goroutine,它逐行扫描文件并获取通道的所有行。当然,执行只会启动它并进一步发展。现在的问题是,在go func()调用之后,我将不得不尝试从频道中读取。我在SO和互联网上找到的解决方案如下:

func readFile(fileName string) {
    cords := make(chan string)
    file := strings.NewReader(fileName)
    go func() {
        scanner := bufio.NewScanner(file)
        for scanner.Scan() {
            cords <- scanner.Text()
        }
        close(cords)
    }()
    for i := 0; i < 100; i++ {
        go getCords(cords)
    }
}

因此,首次执行getCords甚至可能什么都不做,因为goroutine无法设法快速获得通道。下一次迭代可能会完成这项工作,但问题是我必须编写一些数字,例如本例中的100,并且它可能太高,因此通道将在10次迭代中关闭,之后它会&只是浪费时间或者它可能太低,然后我就不会得到所有的结果。

你怎么解决这样的问题,伙计们?有最佳方​​式,还是我必须坚持使用waitGroups

1 个答案:

答案 0 :(得分:1)

我认为是的,使用sync.WaitGroup确保所有goroutine完成工作会更好。一种可能的解决方案:

func getCords(queue Chas string, wg sync.WaitGroup) {
     defer wg.Done()
     // your code 
 }

func readFile(fileName string) {
    cords := make(chan string)
    file := strings.NewReader(fileName)

    go func() {
        scanner := bufio.NewScanner(file)
        for scanner.Scan() {
            cords <- scanner.Text()
        }
        close(cords)
    }()

    wg := sync.WaitGroup{}
    for i := 0; i < 100; i++ {
        wg.Add(1)
        go getCords(cords, wg)
    }
    wg.Wait()
}