2014-09-19 55 views
0

我想重新實現/修改this post第二註釋的代碼。主要退出不久,由於夠程

我想多去例程彈出從棧中的元素(只要在堆棧中的東西),以及其他功能追上他們。

This code in playground

func pop(list *[]int, c chan int) { 
    if len(*list) != 0 { 
     result := (*list)[0] 
     *list = (*list)[1:] 
     fmt.Println("about to send ",result) 
     c <- result 
    } else {return} 
} 

func receiver (c chan int){ 
    result := <- c 
    fmt.Println("received ", result) 
} 

var list = []int{1, 2, 3} 

func main() { 

fmt.Println("Main") 
c := make(chan int) 
go pop (&list, c) 
go pop (&list,c) 
receiver(c) 
fmt.Scan() 

如果我讓接收器(C)一展身手套路,只有「主」將被打印,並計劃將退出,而無需等待掃描()函數。即使添加time.Sleep(2)也不會阻止程序退出。

爲什麼我的程序在沒有任何輸入的情況下退出?

+3

此代碼不安全,因爲兩個'pop's都無鎖訪問共享片。在Playground中'time'和'fmt.Scan'都不能正常操作,但我不知道這是否是這個問題。 – twotwotwo 2014-09-19 02:33:14

+0

是不是去應該爲共享數據自動安全的例程? – meto 2014-09-19 02:39:15

+1

不是;共享片,地圖等需要用['sync.Mutex'](http://golang.org/pkg/sync/)保護;請參閱http://research.swtch.com/godata瞭解原因(從內部代表它們的方式開始)。 – twotwotwo 2014-09-19 02:41:37

回答

2

Scan將不會阻止,如果給定零參數。

注意,遊樂場不會阻塞IO,即使你給它一個說法,代碼

var i int 
fmt.Scan(&i) 

也將無法阻擋,如果你檢查error值返回(第二返回值) ,你應該看到它報告error: EOF

(雖然該樣本會阻擋在遊樂場外)。

編輯:如果你想在輸入塊而不進行虛擬變量,使用Scanln,但它仍然會在操場上失敗。