武漢裝修網(wǎng)站建設(shè)搜索優(yōu)化整站優(yōu)化
🌈Don’t worry , just coding!
內(nèi)耗與overthinking只會削弱你的精力,虛度你的光陰,每天邁出一小步,回頭時發(fā)現(xiàn)已經(jīng)走了很遠。
📗概念
在 Go 語言中,通道(channel)的關(guān)閉是一個重要的概念,允許發(fā)送者通知接收者不再發(fā)送任何值。關(guān)閉通道可以幫助避免死鎖,并使接收者能夠知道何時所有數(shù)據(jù)都已被處理。
💻代碼
通道關(guān)閉
package mainimport "fmt"func main() {jobs := make(chan int, 5) // 創(chuàng)建一個容量為 5 的整型通道 jobsdone := make(chan bool) // 創(chuàng)建一個布爾類型的通道 done// 啟動一個 goroutine 來處理 jobs 通道中的任務(wù)go func() {for {//從 jobs 通道接收任務(wù)。如果通道關(guān)閉且沒有更多數(shù)據(jù),more 將為 false。j, more := <-jobs // 嘗試從 jobs 通道接收任務(wù)if more { // 如果成功接收任務(wù)fmt.Println("received job", j)} else { // 如果通道已關(guān)閉且沒有更多的任務(wù)fmt.Println("received all jobs")done <- true // 向 done 通道發(fā)送信號,表示所有任務(wù)已處理完成//主 goroutine 等待 goroutine 完成所有任務(wù)處理。當(dāng) goroutine 向 done 通道發(fā)送信號后,主 goroutine 將繼續(xù)執(zhí)行。return // 退出 goroutine}}}()// 向 jobs 通道發(fā)送任務(wù)for j := 1; j <= 3; j++ {jobs <- jfmt.Println("sent job", j)}close(jobs) // 關(guān)閉 jobs 通道,表示不再發(fā)送更多任務(wù)fmt.Println("sent all jobs")<-done // 等待 goroutine 完成所有任務(wù)// 嘗試從 jobs 通道接收更多任務(wù)_, ok := <-jobsfmt.Println("received more jobs:", ok)
}
//輸出
//sent job 1
//sent job 2
//sent job 3
//sent all jobs
//received job 1
//received job 2
//received job 3
//received all jobs
//received more jobs: false
🔍理解
- go中關(guān)閉通道的語法:close(myChannel)
- 一旦通道被關(guān)閉,任何后續(xù)的發(fā)送操作都會引發(fā)panic。
- 只由發(fā)送者關(guān)閉通道:通常,只有發(fā)送通道的 goroutine 應(yīng)該關(guān)閉通道。接收者不應(yīng)該關(guān)閉通道,因為這可能會導(dǎo)致其他 goroutine 在嘗試發(fā)送時發(fā)生panic。
- 避免重復(fù)關(guān)閉:關(guān)閉已關(guān)閉的通道會導(dǎo)致恐慌,因此在關(guān)閉通道之前,確保它未被關(guān)閉
- 使用 range 處理通道:使用 range 迭代通道可以簡化關(guān)閉通道后的處理邏輯。
- 從通道返回的第二個值為bool類型,通道開啟時為true,通道關(guān)閉時為false
💡 Tips小知識點
如何檢查通道是否關(guān)閉
value, ok := <-myChannel
if !ok {fmt.Println("Channel is closed")
}
通道關(guān)閉后的情況
package mainimport ("fmt"
)func main() {jobs := make(chan int)// 啟動一個 goroutine 來處理 jobs 通道go func() {for j := range jobs { // 使用 range 迭代接收 jobs 通道的值fmt.Println("Processing job:", j)}fmt.Println("No more jobs, exiting goroutine.")}()// 發(fā)送一些任務(wù)for i := 1; i <= 5; i++ {jobs <- ifmt.Println("Sent job:", i)}close(jobs) // 關(guān)閉通道,表示不再發(fā)送任務(wù)fmt.Println("All jobs sent.")// 等待 goroutine 完成(在這個簡單示例中,它會在接收完所有任務(wù)后自動退出)
}
//輸出
//Processing job: 1
//Sent job: 1
//Sent job: 2
//Processing job: 2
//Processing job: 3
//Sent job: 3
//Sent job: 4
//Processing job: 4
//Processing job: 5
//Sent job: 5
//All jobs sent.
Range over Channels
使用 range 迭代通道是 Go 語言中處理通道的一種簡潔且高效的方式。通過 range 語法,可以自動處理通道的關(guān)閉,簡化了代碼邏輯。
基本用法:
package mainimport "fmt"func main() {//創(chuàng)建通道queue,buffer為2queue := make(chan string, 2)queue <- "one" //發(fā)送消息到通道queue <- "two"close(queue) //關(guān)閉通道for elem := range queue {fmt.Println(elem)}
}//輸出
//one
//two
使用range處理通道的好處
- 使用 range 迭代通道時,Go 會持續(xù)從通道中接收值,直到通道被關(guān)閉為止。
- 當(dāng)通道關(guān)閉后,range 循環(huán)會自動結(jié)束,而不會引發(fā)panic
- 在關(guān)閉通道后,所有未被讀取的值都會被處理完,然后循環(huán)自動退出
- 無需手動檢查通道狀態(tài):使用 range 可以避免手動檢查通道是否關(guān)閉或是否還有值,這樣可以減少代碼的復(fù)雜性。
- 避免死鎖風(fēng)險:在處理通道時,手動檢查通道狀態(tài)可能導(dǎo)致邏輯錯誤,使用 range 可以有效避免這類問題。
💪無人扶我青云志,我自踏雪至山巔。