• 使用chan的时候选择对象还是指针


    使用chan的时候选择对象还是指针

    今天在写代码的时候遇到一个问题,在创建一个通道的时候,不确定创建的通道是使用chan A还是chan *A。

    思考了一下,觉得这个应该和函数一样是一个值传递还是参数传递的问题。然后写了个play验证了一下。

    package main
    
    
    import (
    	"fmt"
    	"time"
    )
    
    
    type B struct {
           Value int
    }
    
    type A struct {
    	Bv B
    }
    
    
    func main() {
      ch := make(chan *A)
    
    	b := B{1}
    	a := A{Bv:b}
    
    	go func(ch chan *A){
    	   for {
    		select {
    		case a := <-ch:
    			a.Bv.Value = 2
    		}
    	    }
    	}(ch)
    
    	ch <- &a
    	time.Sleep(2 * time.Second)
    	fmt.Println(a)
    }
    
    

    这里a.Bv.Value的值改了。 但是如果我这里的ch是make(chan A)的话,则打印出来的值为1了。

    事实证明确实是这样。再去源码里面看看。

    chan的结构是在src/runtime/chan.go 的hchan。我们就看chan.go里面的recv方法

    func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool) {
    

    这个函数就是<-ch 的时候调用的。这里的c代表的就是我们使用的这个chan, ep代表的是ch传输出来的数据存储的位置。

    它在从channel中获取数据的时候调用的是

    recv(c, sg, ep, func() { unlock(&c.lock) }, 3)
    

    看到这个函数里面,就可以看到使用的是typedmemmove 这个函数,这个函数就是c中的memmove。

    将原先的数据,直接拷贝到目标内存中。所以这里说明channel是进行值拷贝的。

    总结

    基本上,chan的使用,如果是结构体的话,建议能使用指针就使用指针。

    备注

    本文golang代码基于go1.11.4

  • 相关阅读:
    Node.js核心模块-net
    ie8兼容rgba写法
    Node.js核心模块-http
    Node.js核心模块-fs文件系统
    js监听滚动结束
    mac本地安装全局包报错npm WARN checkPermissions
    安全测试回顾(一)
    python学习笔记(二):python数据类型
    python学习笔记(一):python简介和入门
    Centos下安装Redis
  • 原文地址:https://www.cnblogs.com/yjf512/p/10417698.html
Copyright © 2020-2023  润新知