Go 并发读取文件的最佳方式

Go 并发读取文件的最佳方式,go,concurrency,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

我有一个这样的文件:

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个城市,甚至是40000个城市。我想得到最好的解决方案,所以我想我应该同时处理这个文件。我有以下代码:

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甚至可能什么都不做,因为goroutine无法以如此快的速度将线路连接到通道。下一次迭代可能会完成这项工作,但问题是我必须写一些数字,如本例中的
100
,它可能太高,因此通道将在大约10次迭代中关闭,然后这只是浪费时间,或者太低,然后我将无法得到所有结果


你们怎么解决这样的问题,伙计们?有没有最佳的方法,或者我必须坚持使用一些
waitGroups

我认为是的,使用
sync.waitGroups
来确保所有的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()
}
func getCords(队列Chas字符串,wg sync.WaitGroup){
推迟工作组完成()
//你的代码
}
func readFile(文件名字符串){
跳线:=制造(成串)
文件:=strings.NewReader(文件名)
go func(){
扫描程序:=bufio.NewScanner(文件)
对于scanner.Scan(){

cords首先编写一个可以正常工作的顺序版本,然后使用评测找出程序最慢的部分,最后开始在相关位置向程序添加并发性。此外,您不会在代码中的任何位置打开任何文件。
file:=strings.NewReader(文件名)
不会从
fileName
操作系统打开和加载数据。open
会这样做:。但是一个goroutine会执行对通道的所有读取。因此,此goroutine会启动,执行会更进一步。那么我应该在哪里调用
go GetRecords()
我已经更新了代码。这不是问题-因为写入
跳线正确,忘记了在有人从频道读取之前发送块goroutine。我不是必须通过指针传递
wg
吗?当我们不知道它将读取多少行时,为什么要为
100
迭代执行for循环?顺便说一句,你的代码没有有两种方式不起作用。首先,getCords不接受按值传递的
sync.WaitGroup
,其次,当我更改它时,程序执行结束时没有结果(就像我将
fmt.Println
添加到getCords时一样).F.e.它刚刚打印了文件名当然,
wg
应该由ponter传递。正如上面的评论员所说,也应该有
Open
。不幸的是,我稍后会在我的笔记本电脑上查看,而不是电话。
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()
}