• Go语法实现分析之chan、go func、类型转换


    背景

    声明、初始化代码,我们都懂,但是它背后是怎么实现的呢?

    类型转换分析

    hello.go

    1. 1 package main
    2. 2
    3. 3 func main() {
    4. 4 var a = "hello"
    5. 5 var b = []byte(a)
    6. 6 println(b)
    7. 7 }

    我们写一份上面的代码

    go tool compile -S ./hello.go | grep "hello.go:5"

     

    我们看最后一行,CALL 调用了runtime.stringtoslicebyte 

    1. func stringtoslicebyte(buf *tmpBuf, s string) []byte {
    2. var b []byte
    3. if buf != nil && len(s) <= len(buf) {
    4. *buf = tmpBuf{}
    5. b = buf[:len(s)]
    6. } else {
    7. b = rawbyteslice(len(s))
    8. }
    9. copy(b, s)
    10. return b
    11. }

    我们可以看到在这个函数里面使用了copy进行复制

    go func语法分析

    hello.go

    1. 1 package main
    2. 2
    3. 3 import "time"
    4. 4
    5. 5 func main() {
    6. 6 go func () {
    7. 7 println("hello world")
    8. 8 }()
    9. 9 time.Sleep(time.Second * 5)
    10. 10 }
    go tool compile -S ./hello.go | grep "hello.go:6"

    在上述图中,我们可以看到编译过程中CALL runtime.newproc 

    Channel语法分析

    1. 1 package main
    2. 2
    3. 3 func main() {
    4. 4 var a = make(chan int, 1)
    5. 5 a <- 666
    6. 6
    7. 7 x := <-a
    8. 8 println(x)
    9. 9 }

    我们写了一份非阻塞发送和接收的代码

    go tool compile -S ./channel_no_block.go

     我们可以在chan.go中找到chansend1和chanrecv1的代码实现

    1. // entry points for <- c from compiled code
    2. //go:nosplit
    3. func chanrecv1(c *hchan, elem unsafe.Pointer) {
    4. chanrecv(c, elem, true)
    5. }

    1. // entry point for c <- x from compiled code
    2. //go:nosplit
    3. func chansend1(c *hchan, elem unsafe.Pointer) {
    4. chansend(c, elem, true, getcallerpc())
    5. }

    channel的panic情况怎么找?

    1. 1 package main
    2. 2
    3. 3 func main() {
    4. 4 var ch chan int
    5. 5 close(ch)
    6. 6 ch <- 1
    7. 7 }

    我们先定义一份肯定会导致channel panic的代码

    go tool compile -S ./channel_panic.go | grep "channel_panic.go:6"

    我们可以看到最后一行CALL 是runtime.chansend1

    我们进入代码看逻辑 

    chan.go:202

    它自定义了一个plainError的错误类型

     我们可以看到有几种情况会抛出这个错误

    1.send on closed channel

    2.close of nil channel

    3.close of closed channel

     

  • 相关阅读:
    【深拷贝和浅拷贝】
    Golang 整合RocketMQ
    C语言:函数
    使用注解实现限流
    用JSX来写Vue3,瞬间找到React 的感觉
    2022年5月28号 SSM框架执行流程图如下。
    Linux安全加固
    300dpi等于多少分辨率?如何给图片修改分辨率大小?
    《MySQL 数据库 (一)》
    吴恩达的机器学习,属实牛逼
  • 原文地址:https://blog.csdn.net/qq_37186127/article/details/125521611