地鼠工厂的秘密:解锁Go语言中goroutine的并发魔法想象一个高效运转的地鼠工厂,每只地鼠都在自己的任务轨道上飞速前进,却又彼此协作,井然有序。这正是Go语言并发编程的魅力所在!通过goroutine和通道,Go让开发者轻松实现高效并发任务,无需繁琐的线程管理或复杂的锁机制。本文将带你走进go
想象一个高效运转的地鼠工厂,每只地鼠都在自己的任务轨道上飞速前进,却又彼此协作,井然有序。这正是Go语言并发编程的魅力所在!通过goroutine和通道,Go让开发者轻松实现高效并发任务,无需繁琐的线程管理或复杂的锁机制。本文将带你走进goroutine的世界,探索它如何化繁为简,成为现代编程中的并发利器。
本文详细介绍了Go语言的核心并发机制——goroutine及其配套工具通道(channel)。从goroutine的轻量级创建到多任务并发的实现,再到通道在任务间安全传值的应用,文章通过代码示例和小测试逐步揭示其工作原理。此外,还探讨了select语句、nil通道、阻塞与死锁等关键概念,并展示了如何通过流水线模式构建高效的并发程序。无论是初学者还是进阶开发者,都能从中窥见Go并发编程的独特优势。
package main
import (
"fmt"
"time"
)
func main() {
go sleepyGopher()
time.Sleep(4 * time.Second)
}
func sleepyGopher() {
time.Sleep(3 * time.Second)
fmt.Println("...snore...")
}
package main
import (
"fmt"
"time"
)
func main() {
for i := 0; i < 5; i++ {
go sleepyGopher()
}
time.Sleep(4 * time.Second)
}
func sleepyGopher() {
time.Sleep(3 * time.Second)
fmt.Println("...snore...")
}
package main
import (
"fmt"
"time"
)
func main() {
for i := 0; i < 5; i++ {
go sleepyGopher(i)
}
time.Sleep(4 * time.Second)
}
func sleepyGopher(id int) {
time.Sleep(3 * time.Second)
fmt.Println("...snore...", id)
}
package main
import (
"fmt"
"time"
)
func main() {
c := make(chan int)
for i := 0; i < 5; i++ {
go sleepyGopher(i, c)
}
for i := 0; i < 5; i++ {
gopherID := <- c
fmt.Println("gopher ", gopherID, " has finished sleeping")
}
}
func sleepyGopher(id int, c chan int) {
time.Sleep(3 * time.Second)
fmt.Println("...snore...", id)
c <- id
}
答:从通道中接收值并赋值给变量的常见方法包括:
package main
import (
"fmt"
"time"
)
func main() {
c := make(chan int)
for i := 0; i < 5; i++ {
go sleepyGopher(i, c)
}
timeout := time.After(2 * time.Second)
for i := 0; i < 5; i++ {
select {
case gopherID := <- c:
fmt.Println("gopher ", gopherID, " has finished sleeping")
case <- timeout:
fmt.Println("my patience ran out")
return
}
}
}
func sleepyGopher(id int, c chan int) {
time.Sleep(time.Duration(rand.Intn(4000)) * time.Millisecond)
c <- id
}
答:select 语句的每个 case 可以包含以下内容:
package main
func main() {
c := make(chan int)
// go func() {c <- 2} ()
<- c // deadlock 死锁
}
package main
func sourceGopher(downstream chan string) {
for _, v := range []string{"hello world", "a bad apple", "goodbye all"}
{
downstream <- v
}
downstream <- ""
}
func filterGopher(upstream, downstream chan string) {
for {
item := <-upstream
if item == "" {
downstream <- ""
return
}
if !strings.Contains(item, "bad") {
downstream <- item
}
}
}
func printGopher(upstream chan string) {
for {
v := <-upstream
if v == "" {
return
}
fmt.Println(v)
}
}
func main() {
c0 := make(chan string)
c1 := make(chan string)
go sourceGopher(c0)
go filterGopher(c0, c1)
printGopher(c1)
}
package main
import (
"fmt"
"strings"
)
func sourceGopher(downstream chan string) {
for _, v := range []string{"hello world", "a bad apple", "goodbye all"}
{
downstream <- v
}
close(downstream)
}
func filterGopher(upstream, downstream chan string) {
for {
item, ok := <-upstream
if !ok {
close(downstream)
return
}
if !strings.Contains(item, "bad") {
downstream <- item
}
}
}
func printGopher(upstream chan string) {
for {
v := <-upstream
if v == "" {
return
}
fmt.Println(v)
}
}
func main() {
c0 := make(chan string)
c1 := make(chan string)
go sourceGopher(c0)
go filterGopher(c0, c1)
printGopher(c1)
}
package main
import (
"fmt"
"strings"
)
func sourceGopher(downstream chan string) {
for _, v := range []string{"hello world", "a bad apple", "goodbye all"}
{
downstream <- v
}
close(downstream)
}
//func filterGopher(upstream, downstream chan string) {
// for {
// item, ok := <-upstream
// if !ok {
// close(downstream)
// return
// }
// if !strings.Contains(item, "bad") {
// downstream <- item
// }
// }
//}
func filterGopher(upstream, downstream chan string) {
for item := range upstream {
if !strings.Contains(item, "bad") {
downstream <- item
}
}
close(downstream)
}
//func printGopher(upstream chan string) {
// for {
// v := <-upstream
// if v == "" {
// return
// }
// fmt.Println(v)
// }
//}
func printGopher(upstream chan string) {
for v := range upstream {
fmt.Println(v)
}
}
func main() {
c0 := make(chan string)
c1 := make(chan string)
go sourceGopher(c0)
go filterGopher(c0, c1)
printGopher(c1)
}
goroutine和通道是Go语言在并发编程领域的杀手锏,它们让复杂的并发任务变得简单而优雅。通过轻量级的goroutine,开发者可以轻松启动成千上万的任务;而通道则提供了安全的数据传递和同步手段,确保程序高效运行。无论是处理多任务并行,还是避免死锁陷阱,Go的并发模型都展现了无与伦比的灵活性。掌握这些工具,你将能在地鼠工厂中指挥千军,打造属于自己的并发杰作!
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!