在通道中使用引用错误/不好吗?

问题描述 投票:0回答:1

说我有很多字符串,除了常规的sort.Sort和sort.Slice等,我想对它们进行排序。我想使用多个内核来加快处理速度。因此,在阅读大列表时,我将字符串添加到2个不同的切片中,这些字符串以a-m和n-z开头(出于参数考虑)。

同时,我启动了多个go例程来读取通道的字符串切片,然后对它们自己的子列表进行排序。到目前为止,对列表进行了很好的“潜在”并行处理,因此我的排序时间有效地减少了一半。大。现在我的问题是如何将结果返回到主goroutine?

最初,每个goroutine都有2个通道,一个用于传入未排序列表,另一个用于排序列表。是的,它可以工作……但是使用了太多的内存(嘿,我给出了我要为此测试修补的数据量,这可能不是不合理的)。但是后来我想到,在通道上传递切片实际上只是在传递引用,所以我实际上不需要将任何内容传递回来。不必将返回的排序列表放在返回旅程的通道中,显然在记忆力上要少得多,但是(对我来说)有气味。

这意味着我可以将其中一个goroutine进行分类,而主要的goroutine(理论上)可以操纵相同的列表。只要遵守纪律就不会成为问题,但显然仍然是一个问题。在Go中是否有公认的最佳实践来说明不应将引用作为输入从一个goroutine传递给另一个goroutine ....但是可以接受的是,可以通过通道返回生成参考数据的goroutine(因为goroutine可以停止使用参考)。

[在有人说之前,是的,我知道我不必通过渠道等将它们传递给我,但这只是我正在修补并让我思考的情况。

我知道波浪形和波浪形。这是显示上面代码的最小代码子集。

package main

import (
    "bufio"
    "fmt"
    "os"
    "sort"
    "strings"
    "sync"
    "time"
)

var wg sync.WaitGroup

func sortWordsList(id int, ch chan []string ) {

    l := <- ch
    sort.Strings(l)
    wg.Done()
}

func main() {
    file, err := os.Open("big.txt")
    defer file.Close()

    if err != nil {
        fmt.Printf("BOOM %s\n", err.Error())
        panic(err)
    }

    // Start reading from the file with a reader.
    reader := bufio.NewReader(file)

    inCh1 := make(chan []string, 1000)
    inCh2 := make(chan []string, 1000)

    go sortWordsList(1, inCh1)
    go sortWordsList(2, inCh2)

    wg.Add(2)

    words1 := []string{}
    words2 := []string{}

    for {
        line, err := reader.ReadString('\n')
        if err != nil {
            break
        }

        sp := strings.Split(line, " ")
        for _,w := range sp {
            word := strings.ToLower(w)
            word = strings.TrimSuffix(word, "\n")
            if len(word) > 0 {
                // figure out where to go.
                // arbitrary split.
                if word[0] < 'm' {
                    words1 = append(words1, word)
                } else {
                    words2 = append(words2, word)
                } 
            }
        }
    }

    inCh1 <- words1
    inCh2 <- words2

    close(inCh1)
    close(inCh2)

    wg.Wait()

    // now have sorted words1 and words2 slices.
}
go channel
1个回答
0
投票

传递引用没有错。只要您同步对引用的访问,就可以传递引用并在发送goroutine中继续使用它。对于数组或大型结构之类的大型对象,传递引用通常是避免昂贵拷贝的合理做法。另外,避免传递引用意味着避免传递切片和图或包含切片,图或对其他结构的引用的任何内容。

您已经知道,您实际上并不需要通道,只需在构造切片后启动goroutine,然后直接传递切片即可。

go sortWordsList(words1)
go sortWordsList(words2)

或:

go sort.Strings(words1)
go sort.Strings(words2)
© www.soinside.com 2019 - 2024. All rights reserved.