为了账号安全,请及时绑定邮箱和手机立即绑定

改变合并排序中通道的使用会杀死我的程序;或者我在处理 goroutine 时误解了范围?

改变合并排序中通道的使用会杀死我的程序;或者我在处理 goroutine 时误解了范围?

Go
侃侃无极 2023-08-07 15:25:43
几天前,我在 Code Review 网站上发布了这个主题。在其中,我详细介绍了我在合并排序代码中实现 goroutine 的第一次尝试,虽然它运行良好,但我希望有更好的实现。当我想得更多时,我有了一个我认为可靠的想法:与其在将两侧合并在一起之前不断等待左侧和右侧都完成,为什么不采用从左侧,因为它正在对自己进行排序,并对从右侧获得的单个块进行排序,然后对它们进行排序?我尝试重组我的代码,但遇到了一些问题:据我所知,我对基本情况的实现导致了巨大的问题,或者我误解了 goroutine 的范围,并告诉通道在何时关闭它们在不同的排序块中仍在使用。我希望有人可以帮助我完善我的理解,或者,如果我的代码以简单的方式被破坏,帮助我理解我将在此代码之后提出的问题:package mainimport (    "crypto/rand"    "fmt"    "os"    "strconv")var (    nums    []byte //The slice of numbers we want to sort    numVals int    = -1)//User can optionally add a parameter that determines how many random numbers will be sorted//If none are provided, 100 will be usedfunc main() {    if len(os.Args) >= 2 {        numVals, _ = strconv.Atoi(os.Args[1])    } else {        numVals = 2    }    nums = initSlice()    ms := make(chan byte)    go mergeSort(nums, ms)    pos := 0    for val := range ms {        nums[pos] = val        pos++    }    for _, value := range nums {        fmt.Printf("%d\n", value)    }}func initSlice() []byte {    vals := make([]byte, numVals)    _, err := rand.Read(vals)    if err != nil {        panic(err)    }    return vals}func mergeSort(arr []byte, ms chan byte) {    if len(arr) <= 1 {        if len(arr) == 1 { //base case            ms <- arr[0]        }        close(ms)        return    }    leftMS := make(chan byte)    go mergeSort(arr[:len(arr)/2], leftMS)    rightMS := make(chan byte)    go mergeSort(arr[len(arr)/2:], rightMS)    left, lOK := <-leftMS    right, rOK := <-rightMS    for lOK && rOK {        leftLeast := left <= right        if leftLeast {            ms <- left            left, lOK = <-leftMS        } else {            ms <- right            right, lOK = <-rightMS        }    }    if lOK {        ms <- left        for val := range leftMS {            ms <- val        }    }总的来说,我最大的问题是,假设我们有以下类型:如果我当前正在处理&ldquo;38&rdquo;和&ldquo;27&rdquo;配对,并且关闭该 ms 通道,我希望它与在 main 中启动所有内容的通道不是同一个通道?如果没有,有没有办法可以在保留名称的同时递归创建新频道?希望这一切都有意义并感谢您的帮助。
查看完整描述

1 回答

?
Qyouu

TA贡献1786条经验 获得超11个赞

您的频道使用不是您的问题。你的程序有两个问题。

首先,您必须将结果收集到主 goroutine 中的单独数组中,否则,您将在排序时修改正在排序的数组。

二、这个块:

       } else {
            ms <- right
            right, lOK = <-rightMS

它应该是

right, rOK = <-rightMS

您正在设置lOKrightMS而不是rOK


查看完整回答
反对 回复 2023-08-07
  • 1 回答
  • 0 关注
  • 61 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信