以下代码在golang中实现yield模式。作为一项实验,我正在实施一个<div id="cssmenu" class="align-center">
<ul>
<li><a href="#">FORD</a>
<ul>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/ford-courier-seat-covers">COURIER</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Ford+Ranger">RANGER</a></li>
</ul>
</li>
<li><a href="#">GREAT WALL</a>
<ul>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/great-wall-0311-current">V200/V240</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/great-wall-x200x240-series">X200/X240</a></li>
</ul>
</li>
<li><a href="#">HOLDEN</a>
<ul>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Holden+Colorado">COLORADO</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Holden+Rodeo">RODEO</a></li>
</ul>
</li>
<li><a href="#">ISUZU</a>
<ul>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Isuzu+DMAX">DMAX</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/isuzu-mu-x-0614-current">MUX</a></li>
</ul>
</li>
<li><a href="#">LAND ROVER</a>
<ul>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Land+Rover+Defender">DEFENDER</a></li>
</ul>
</li>
<li><a href="#">MAZDA</a>
<ul>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/mazda-bravo-0699-1106-series-1-2-series-2-facelift">BRAVO</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Mazda+BT50">BT50</a></li>
</ul>
</li>
<li><a href="#">MITSUBISHI</a>
<ul>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Mitsubishi+Triton">TRITON</a></li>
</ul>
</li>
<li><a href="#">NISSAN</a>
<ul>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Nissan+Navara+D22">NAVARA D22</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/nissan-navara-d23-0315-current-np300-dxrxstst-x">NAVARA D23</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Nissan+Navara+D40">NAVARA D40</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Nissan+Patrol+Wagon">PATROL WAGON</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Nissan+Patrol+Utilities">PATROL UTILITIES</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/nissan-pathfinder-0805-current-r51-stst-l">PATHFINDER</a></li>
</ul>
</li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/paratus">PARATUS</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/stratos">STRATOS</a></li>
<li><a href="#">TOYOTA</a>
<ul>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Toyota+Hilux">HILUX</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/toyota-lc200-1008-current-gxgxl">LC200</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Toyota+LC100+Series">LC100</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Toyota+LC80+Series">LC80</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Toyota+LC79+Series">LC79</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Toyota+LC78+Series">LC78</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/toyota-lc76-0307-0812-wagonworkmategxl">LC76</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Toyota+LC75+Series">LC75</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Toyota+LC70+Series">LC70</a></li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/?category=Toyota+Prado">LC PRADO</a></li>
</ul>
</li>
<li><a href="#">VOLKSWAGEN</a>
<ul>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/volkswagen-amarok-0511-current-amaroktrendlinehighlineultimate">AMAROK</a></li>
</ul>
</li>
<li><a href="https://dani-lane-743w.squarespace.com/seat-covers/universal">UNIVERSAL</a></li>
</ul>
</div>
生成器。但是,当我将切片all permutations
返回到通道时,如果我没有创建数组的新副本,则会得到错误的结果。
请参阅“A
”附近的代码。有人能解释一下这里发生的事情吗?我认为,由于通道没有缓冲,我保证在将数组的切片发布到通道后,我确保在继续之前消耗结果。
???
如果我不复制数据,我会得到以下结果:
package main
import (
"fmt"
)
func swap(A []int, i int, j int) {
t := A[i]
A[i] = A[j]
A[j] = t
}
func recurse(A []int, c chan []int, depth int) {
if depth == len(A) {
// ??? Why do I need to copy the data?
// If I do c <- A I get an incorrect answer.
ra := make([]int, len(A))
copy(ra, A)
c <- ra
return
}
for i := depth; i < len(A); i++ {
swap(A, depth, i)
recurse(A, c, depth+1)
swap(A, depth, i)
}
}
func yieldPermutations(A []int, c chan []int) {
recurse(A, c, 0)
close(c)
}
func main() {
A := []int{1, 2, 3}
c2 := make(chan []int)
go yieldPermutations(A, c2)
for v := range c2 {
fmt.Println(v)
}
}
显然,正确的结果(我们通过数据复制获得)是:
[1 3 2]
[1 3 2]
[2 3 1]
[2 3 1]
[3 1 2]
[3 1 2]
答案 0 :(得分:4)
认为这段代码就像Python中的生成器/产量一样是错误的,而这是造成错误的原因。
在Python中,当您从生成器请求下一个项目时,生成器开始执行并在到达下一个yield <value>
语句时停止。 Python的生成器中没有并行性:消费者运行直到它想要一个值,然后生成器运行直到它产生一个值,然后消费者获取值并继续执行。
在你的go代码中,goroutine与消耗项目的代码同时执行。一旦从主代码中从通道读取项目,goroutine就会同时生成下一个项目。 goroutine和消费者都会一直运行,直到它们到达通道发送/接收,然后将值从goroutine发送到消费者,然后它们都继续执行。
这意味着A
的后备数组会被同时修改,因为goroutine会生成下一个项目。这是一种导致意外输出的竞争条件。要证明这是一场比赛,请在频道发送后插入time.Sleep(time.Second)
。然后代码产生正确的结果(虽然很慢):https://play.golang.org/p/uEa_k6Brcc