2013-02-01 134 views
1

我有一個正在偵聽TCP連接並將這些通道發送回主循環的去程序。我在做例行程序的原因是讓這個監聽不阻塞,並且能夠同時處理活動連接。從Go通道獲取價值

我有一個空的默認情況下,像這樣的select語句來實現這一點:

go pollTcpConnections(listener, rawConnections) 

for { 
    // Check for new connections (non-blocking) 
    select { 
    case tcpConn := <-rawConnections: 
     currentCon := NewClientConnection() 
     pendingConnections.PushBack(currentCon) 
     fmt.Println(currentCon) 
     go currentCon.Routine(tcpConn) 
    default: 
    } 
    // ... handle active connections 
} 

這裏是我的pollTcpConnections常規:

func pollTcpConnections(listener net.Listener, rawConnections chan net.Conn) { 
    for { 
    conn, err := listener.Accept() // this blocks, afaik 
    if(err != nil) { 
     checkError(err) 
    } 
    fmt.Println("New connection") 
    rawConnections<-conn 
    } 
} 

的問題是,我從來沒有收到這些連接。如果我做一個堵的方式,像這樣:

for { 
    tcpConn := <-rawConnections 
// ... 
} 

我收到的連接,但它會阻止......我試圖緩衝通道爲好,但同樣的事情發生。我在這裏錯過了什麼?

+3

請參閱[這個問題](http://stackoverflow.com/questions/14633373/how-to-do-nothing-when-no-channel-is-ready-to-beread)爲答案。 – thwd

回答

1

有點難以分辨爲什麼你沒有看到基於現有代碼的任何連接。您的示例有一個問題,您在select聲明中有一個空的default個案,然後我們無法看到此for循環中還發生了什麼。您編寫它的方式,該循環可能永遠不會屈服於調度器。你基本上是在說:「從渠道中獲得一件東西,沒有一件好東西,重新開始,從渠道中獲得一件東西!」,但你永遠不會等待。當你做了一些阻止你的goroutine的動作時,該goroutine屈服於調度器。因此,當你以正常的方式閱讀頻道時,如果沒有價值可讀,該goroutine被阻止閱讀。由於它被阻塞,它也讓調度器允許其他的goroutine繼續在底層線程上執行。我相當肯定這就是爲什麼你的select與一個空的default打破;你正在導致該goroutine無限循環到for循環,而沒有屈服於調度器。

目前還不清楚pendingConnections的作用是什麼,或者它是否需要。

從行爲中無法分辨的另一件事是您的checkError函數。例如,它不會繼續到for循環的頂部,或保釋。

無論如何,它看起來像這是比它需要更復雜。只需要一個將新連接作爲一個參數的函數,然後在連接時在新的goroutine中啓動它。我總是寫這樣的:

func handleConnection(c net.Conn) { 
    // do something with your connection here. 
} 

for { 
    // Wait for a connection. 
    conn, err := l.Accept() 
    if err != nil { 
     // do something with your error. You probably want to break or return here. 
     break 
    } 
    // handle each connection in a new goroutine 
    go handleConnection(conn) 
} 

這是多還是少,他們在the documentation做什麼。

+1

謝謝你的回答。湯姆指出了另一個有同樣問題的問題。添加一個runtime.Gosched()「固定」的問題,但我明白,這可能意味着我的設計很糟糕。 你的例子是OK的,除了那個l.Accept()塊。我想繼續在同一個循環中進行操作。 – alf