Golang协程常见面试题代码分析
更新时间:2023-11-141. 协程和线程的区别
线程是进程的一部分,但线程依赖于进程,也就是说,一个线程不能脱离进程单独存在,所以线程是有限资源;而协程则是不依赖进程或线程存在的,它是轻量级的线程,而且一个进程可以拥有多个协程。
// Go中开启协程的例子 func main() { go sayHello() // 开启协程 fmt.Println("main function") } func sayHello() { fmt.Println("Hello") }
2. 协程的并发与底层实现
Go的协程实现了轻量级的线程,在Go语言中,所有的协程都运行在相同的系统线程中,称为 m:n 调度,其中m个协程可以运行在n个线程的上下文中,Go运行时有一个调度器,协程间的切换就由这个调度器完成,因此切换非常快速。
// 协程并发的例子 func main() { for i := 1; i <= 5; i++ { go printNum(i) } time.Sleep(time.Second * 1) } func printNum(i int) { fmt.Println("Num is", i) }
3. 协程的通道(Channel)
Go语言中的协程间通信可以通过通道来实现,通道是一种可带缓存的类型,可以让协程之间进行通信和同步,从而实现协程间的数据共享。通道有两种类型:有缓存和无缓存,无缓存通道在进行数据传输时需要先等待另一个协程接收数据,而有缓存通道则不需要。
// 带缓存的通道 func main() { ch := make(chan int, 2) // 带有2缓存的通道 ch <- 1 ch <- 2 fmt.Println(<-ch, <-ch) } // 无缓存的通道 func main() { ch := make(chan int) go func() { ch <- 1 }() fmt.Println(<-ch) }
4. 协程的错误处理
协程与其他线程一样,也有可能会发生错误,当协程发生错误时,程序需要及时处理,否则程序可能崩溃。可以通过recover()函数来捕获协程中的错误,同时使用defer语句将程序从崩溃中恢复。Go语言中还提供了Panic和Recover机制来处理异常情况。
// 协程错误处理的例子 func main() { defer func() { if err := recover(); err != nil { log.Println(err) } }() go func() { panic("panic happened") }() time.Sleep(time.Millisecond * 10) }总结:通过上述代码示例的分析,我们可以知道协程可以轻松地实现并发编程,而且Go语言的协程相对于其他语言的协程来说有更高的执行效率。同时,协程之间通信可以使用通道来完成,而异常情况的处理也得到了良好的支持。