• 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

     

  • 相关阅读:
    有趣的java面试题-基础篇(一)
    基于数学形态学的路面裂缝图像处理技术-含Matlab代码
    Linux学习笔记6 - 系统启动流程
    内存取证之volatility及案例演示
    《MongoDB入门教程》第12篇 查询结果排序
    centos 非docker环境搭建nacos集群
    数据结构之详解【Map和Set】
    四、集合
    【抽样技术】CH2 简单随机抽样补充——比率估计与回归估计
    上半年收入超耐克中国、大于两个李宁,安踏领跑背后的韧性
  • 原文地址:https://blog.csdn.net/qq_37186127/article/details/125521611