开发者

一文帮你搞懂Go面试中常问的channel问题

开发者 https://www.devze.com 2023-11-21 10:46 出处:网络 作者: 王中阳Go
目录一图胜千言select先说phpswitch...case...再编程说select...case..select类比switch经典示例channel1.从已经关闭并且没有值的通道中取值2.从已经关闭并且有值的通道中取值3.一图胜千言总结一图胜千编程言
目录
  • 一图胜千言
  • select
    • 先说phpswitch...case...
    • 编程说select...case..
    • select类比switch
    • 经典示例
  • channel
    • 1.从已经关闭并且没有值的通道中取值
    • 2.从已经关闭并且有值的通道中取值
    • 3.一图胜千言
  • 总结

    一图胜千编程

    下面的表格中总结了对不同状态下的通道执行相应操作的结果。

    一文帮你搞懂Go面试中常问的channel问题

    注意:对已经关闭的通道再执行 close 也会引发 panic。

    又有朋友催更,让我出面试题系列了,安排!

    这篇文章将重点讲解Go面试android进阶知识点:select和channel。

    select

    先说switch...case...

    switch...case... 很常用,且很好理解。其作用和if...else...一样。

    区别是switch...case 相比于if...else...能让我们的代码看起来更清晰,更好理解。

    再说select...case..

    golang 的 select 就是监听 IO 操作,当 IO 操作发生时,触发相应的动作。 

    所说的IO操作就是对channle的操作:向通道发送数据,或者从通道中读取数据。

    在执行select语句的时候,运行时系统会自上而下地判断每个case中的发送或接收操作是否可以被立即执行。

    什么是立即执行呢?

    立即执行:意思是当前Goroutine不会因当前操作而被阻塞

    select类比switch

    select的用法与switch非常类似,由select开始一个新的选择块,每个选择条件由case语句来描述。

    与switch语句可以选择任何可使用相等比较的条件相比,select有比较多的限制,其中最大的一条限制就是每个case语句里必须是一个IO操作。

    确切的说,应该是一个面向channel的IO操作。

    经典示例

    package main
    import "fmt"
    func main() {
       ch1 := make(chan int, 1)
       ch1 <- 2
       select {
       case v := <-ch1:
          fmt.Println("取到的数据:", v)
       case ch1 <- 1:
          fmt.Println("写入数据")
       }
    }

    运行结果

    一文帮你搞懂Go面试中常问的channel问题

    channel

    goroutine和channel作为go语言中最重要的两个知识点,一定要搞清楚。

    大家容易出错的知识点是以下3点,尤其是最后一点:

    • nil channel代表channel未初始化,向未初始化的channel读写数据会造成阻塞
    • 关闭(close)未初始化的channel会引起panic。
    • 从一个关闭的并且没有值的通道执行接收操作会得到对应类型的零值,并不会引起panic。

    1.从已经关闭并且没有值的通道中取值

    package main
    
    import "fmt"
    
    //从关闭的通道中取值示例:
    func main() {
       //声明实例化通道ch1
       ch1 := make(chan int, 1)
       //关闭通道
       close(ch1)
       select {
       //通通道ch1中取值
       case v := <-ch1:
          fmt.Printf("从ch1中取值:%d\n", v)
       default:
          fmt.Println("默认case")
       }
    }
    

    运行结果

    和我们预想中的一样,取到了对应的零值: 

    一文帮你搞懂Go面试中常问的channel问题

    2.从已经关闭并且有值的通道中取值

    我们稍微修改一下上面的代码

    package main
    import "fmt"
    //从关闭的通道中取值示例:
    func main() {
       //声明实例化通道ch1
       ch1 := make(chan int, 1)
       //向通道中赋值
       ch1 <- 1
       //关闭通道
       close(ch1)
       //关闭之后取值
       after_close_value := <-ch1
       fmt.Printf("关闭之后取值:%d\n", after_close_value) //打印结果:关闭之后取值:1
       select {
       //通通道ch1中取值
       case v := <-ch1:
          fmt.Printf("从ch1中取值:%d\n", v) //打印结果:从ch1中取值:0
       default:
          fmt.Println("默认case")
       }
    }

    运行结果

    运行结果和我们预想中的一样:

    • 通道关闭后,如果通道中仍然有值,还是可以正常取到通道中的值的。
    • 通道关闭后,如果通道中已经没有值android了,再从通道中取值,并不会引起panic,而是会取到对应类型的零值。

    一文帮你搞懂Go面试中常问的channel问题

    3.一图胜千言

    下面的表格中总结了对不同状态下的通道执行相应操作的结果。

    一文帮你搞懂Go面试中常问的channel问题

    注意:对已经关闭的通道再执行 close 也会引发 panic。

    总结

    这篇文章解析了Go语言中select和channel在面试中可能遇到的进阶知识点。

    到此这篇关于一文帮你搞懂Go面试中常问的channel问题的文章就介绍到这了,更多相关Go面试内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号