c语言编程笔录

首页 >   > 笔记大全

笔记大全

Golang协程常见面试题代码分析

更新时间:2023-11-14

1. 协程和线程的区别

线程是进程的一部分,但线程依赖于进程,也就是说,一个线程不能脱离进程单独存在,所以线程是有限资源;而协程则是不依赖进程或线程存在的,它是轻量级的线程,而且一个进程可以拥有多个协程。

// 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语言的协程相对于其他语言的协程来说有更高的执行效率。同时,协程之间通信可以使用通道来完成,而异常情况的处理也得到了良好的支持。