dongzhuo2371 2017-05-01 16:24
浏览 132
已采纳

实施Heap的置换算法时Golang范围内的通道具有奇怪的行为

I was trying to implement Heap's Algorithm in go using channels. The code below is working fine when just printing the slices on the screen, but when using channels to delivery the arrays to a for/range loop on main function some unexpected behaviour occurs and the slices/arrays are printed in duplicity and not all permutations are sent. I thought that maybe i'm closing the channel earlier than the main function is able to print the results but i wouldn't expect that double print. Why is this happening and how can i make it work.

package main

import "fmt"

func perm(a []int64) {
    var n = len(a)
    var c = make([]int, n)
    fmt.Println(a)
    i := 0
    for i < n {
        if c[i] < i {
            if i%2 == 0 {
                a[0], a[i] = a[i], a[0]
            } else {
                a[c[i]], a[i] = a[i], a[c[i]]
            }
            fmt.Println(a)
            c[i]++
            i = 0
        } else {
            c[i] = 0
            i++
        }
    }
}

func permch(a []int64, ch chan<- []int64) {
    var n = len(a)
    var c = make([]int, n)
    ch <- a
    i := 0
    for i < n {
        if c[i] < i {
            if i%2 == 0 {
                a[0], a[i] = a[i], a[0]
            } else {
                a[c[i]], a[i] = a[i], a[c[i]]
            }
            ch <- a
            c[i]++
            i = 0
        } else {
            c[i] = 0
            i++
        }
    }
    close(ch)
}

func main() {
    var i = []int64{1, 2, 3}
    fmt.Println("Without Channels")
    perm(i)
    ch := make(chan []int64)
    go permch(i, ch)
    fmt.Println("With Channels")
    for slc := range ch {
        fmt.Println(slc)
    }

}
  • 写回答

2条回答 默认 最新

  • douque9982 2017-05-01 17:05
    关注

    It looks like permch is modifying a at the same time as main is printing it, so your output is garbled.

    I can think of three easy fixes:

    1. Guard access to a with a mutex.
    2. Put a copy of a on the channel:
    3. Have some kind of return signal from main that it has printed and permch can continue. (don't really recommend this, but it works).

    Number 2 is pretty simple:

    a2 := make([]int64, len(a))
    copy(a2,a)
    ch <- a2
    

    and is what I would recommend.

    For #1, just declare a var m sync.Mutex as a package variable and Lock is anytime you read or modify a. This is a race condition though between the reader and the next modification, as you pointed out, so it probably isn't a good solution after all.

    fixed version on playground using #3

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 乌班图ip地址配置及远程SSH
  • ¥15 怎么让点阵屏显示静态爱心,用keiluVision5写出让点阵屏显示静态爱心的代码,越快越好
  • ¥15 PSPICE制作一个加法器
  • ¥15 javaweb项目无法正常跳转
  • ¥15 VMBox虚拟机无法访问
  • ¥15 skd显示找不到头文件
  • ¥15 机器视觉中图片中长度与真实长度的关系
  • ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
  • ¥15 java 的protected权限 ,问题在注释里
  • ¥15 这个是哪里有问题啊?