使用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

使用chan的时候选择对象还是指针的更多相关文章

  1. Golang - 指针与引用

    ​ Golang有指针 , 那么一切数据都是值传递吗 ? 都需要用户进行指针传递吗, 其实不然, 对于Go语言, 虽然有指针, 但是其也有引用传递. 是不是很绕, 因为引用传递就是指针传递哇 . 我们 ...

  2. golang的nil

    golang中什么样的类型可以赋值nil? 类型文档中有注定"uninitialized value is nil"的类型都可以赋值nil. golang的基本类型不能赋值nil: ...

  3. nsq topic

    与Topic相关的代码主要位于nsqd/topic.go中. 上一篇文字我们讲解了下nsq的启动流程.对nsq的整体框架有了一个大概的了解.本篇文章就是由大到小.对于topic这一部分进行详尽的讲解. ...

  4. Go素数筛选分析

    Go素数筛选分析 1. 素数筛选介绍 学习Go语言的过程中,遇到素数筛选的问题.这是一个经典的并发编程问题,是某大佬的代码,短短几行代码就实现了素数筛选.但是自己看完原理和代码后一脸懵逼(仅此几行能实 ...

  5. go语言学习--指针的理解

    Go 的原生数据类型可以分为基本类型和高级类型,基本类型主要包含 string, bool, int 及 float 系列,高级类型包含 struct,array/slice,map,chan, fu ...

  6. go学习 --- Chan (通道)

    Golang使用Groutine和channels实现了CSP(Communicating Sequential Processes)模型,channles在goroutine的通信和同步中承担着重要 ...

  7. Golang 中的指针 - Pointer

    http://www.cnblogs.com/jasonxuli/p/6802289.html   Go 的原生数据类型可以分为基本类型和高级类型,基本类型主要包含 string, bool, int ...

  8. go之变量、指针、引用地址

    一.值类型 定义和说明 定义:变量直接指向存在内存中的值,我们称之为值类型. 值类型的变量的值存储在栈中. 值类型 将一个变量赋值给另一个变量 被称为值拷贝 实例 package main impor ...

  9. Go语言基础之指针

    区别于C/C++中的指针,Go语言中的指针不能进行偏移和运算,是安全指针. 要搞明白Go语言中的指针需要先知道3个概念:指针地址.指针类型和指针取值. Go语言中的指针 Go语言中的函数传参都是值拷贝 ...

随机推荐

  1. 科学计算工具Numpy

    参考学习资料: Python.NumPy和SciPy介绍:http://cs231n.github.io/python-numpy-tutorial NumPy和SciPy快速入门:https://d ...

  2. Python3 模拟登录知乎(requests)

    # -*- coding: utf-8 -*- """ 知乎登录分为两种登录 一是手机登录 API : https://www.zhihu.com/login/phone ...

  3. 【游戏开发】在Lua中实现面向对象特性——模拟类、继承、多态

    一.简介 Lua是一门非常强大.非常灵活的脚本语言,自它从发明以来,无数的游戏使用了Lua作为开发语言.但是作为一款脚本语言,Lua也有着自己的不足,那就是它本身并没有提供面向对象的特性,而游戏开发是 ...

  4. vue enter事件无效,加入native

    <Input type="password" v-model="password" placeholder="password" @k ...

  5. Arrays.asList 为什么不能 add 或者 remove 而 ArrayList 可以

    分析如下例子: 1 import java.util.Arrays; 2 import java.util.List; 3 4 5 public class Test { 6 public stati ...

  6. Treap与fhq_Treap学习笔记

    1.普通Treap 通过左右旋来维护堆的性质 左右旋是不改变中序遍历的 #include<algorithm> #include<iostream> #include<c ...

  7. java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApplicationBuilder.<init>([Ljava

    搭建spring cloud的时候,报以下错误: java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApplica ...

  8. 【JVM虚拟机】(9)-- JVM是如何处理异常的

    [JVM虚拟机](9)-- JVM是如何处理异常的 上篇博客我们简单说过异常信息是存放在属性表集合中的Code属性表里,那么这篇博客就单独讲Code属性表中的exception_table. 在讲之前 ...

  9. 带着新人看java虚拟机05(多线程篇)

    上一篇我们主要是把一些基本概念给说了一下以及怎么简单的使用线程池,我们这一节就来看看线程池的实现: 1.线程池基本参数 以Executors.newFixedThreadPool()这种创建方式为例: ...

  10. 闲聊js中的apply、call和arguments

    JavaScript提供了apply和call两种调用方式来确定函数中的this的指向,在现实编码中,我确实 很少接触到这两个方法.但很无奈,很多面试题都要考这两种方法,我又没怎么用到,所以我们先来 ...