原文: https://studygolang.com/articles/12310/comment/17923

--------------------------------------------------------------------------------------

Time won't go back I won't turn back.

时光不会倒着走,我也不会再回头。

其实这个问题其实是出现在引用类型( 此处是slice )上, 这个是 slice 的数据结构,它很简单,一个指向真实 array 地址的指针 ptr ,slice 的长度 len 和容量 cap 。

结构图解1

每次cap改变的时候指向array内存的指针都在变化, 在实际使用中,我们最好事先预期好一个cap,这样在使用append的时候可以避免反复重新分配内存复制之前的数据,减少不必要的性能消耗。

现在上实例,来看看坑所在:

package main

import "fmt"
import "time" func main() {
ch := make(chan []byte, 10)
go func() {
for {
select {
case data := <-ch:
fmt.Println(string(data))
}
}
}()
data := make([]byte, 0, 32)
data = append(data, []byte("bbbbbbbbbb")...)
ch <- data // fmt.Printf("%p\n", data)
data = data[:0]
// fmt.Printf("%p\n", data) data = append(data, []byte("aaa")...)
ch <- data time.Sleep(time.Second * 5)
}

预测的运行结果:

bbbbbbbbbb

aaa

但是肯定是有坑的

前面新起了一个协程来等待通道接受信息, 主进程继续执行, 当data传递给了通道之后, 立刻修改了data指向数组的值(第二次append), 所以通道第一次接收的值就已经改变了, 因为我们传递的是引用,不是值类型。

解决方案呢就是加锁 或者新变量拷贝。

【转】Golang关于channel传递引用引发的坑的更多相关文章

  1. 深入学习golang(2)—channel

    Channel 1. 概述 “网络,并发”是Go语言的两大feature.Go语言号称“互联网的C语言”,与使用传统的C语言相比,写一个Server所使用的代码更少,也更简单.写一个Server除了网 ...

  2. golang的Channel

    golang的Channel Channel 是 golang 一个非常重要的概念,如果你是刚开始使用 golang 的开发者,你可能还没有真正接触这一概念,本篇我们将分析 golang 的Chann ...

  3. Golang 入门 : channel(通道)

    笔者在<Golang 入门 : 竞争条件>一文中介绍了 Golang 并发编程中需要面对的竞争条件.本文我们就介绍如何使用 Golang 提供的 channel(通道) 消除竞争条件. C ...

  4. 传递引用类型参数的两种方式(转自 MSDN)

    引用类型的变量不直接包含其数据:它包含的是对其数据的引用.当通过值传递引用类型的参数时,有可能更改引用所指向的数据,如某类成员的值(更改属性的值),但是无法更改引用本身的值:也就是说,不能使用相同的引 ...

  5. 传递引用类型参数(ref)

    引用类型的变量不直接包含其数据:它包含的是对其数据的引用. 当通过值传递引用类型的参数时,有可能更改引用所指向的数据,如某类成员的值. 但是无法更改引用本身的值:也就是说,不能使用相同的引用为新类分配 ...

  6. JAVA一个关于传递引用的测试

    以下测试主要为了说明:对传递对象或传递引用进行修改,对最终值的影响情况 public class PassTest {     @Before     public void setUp() thro ...

  7. thread - 传递引用参数

    当给 thread 的执行函数传递指针参数时,没有任何问题,但是如果想传递引用,按照普通函数的调用方法会遇到编译失败: #include <iostream> #include <t ...

  8. 对象引用 方法传参 值传递 引用传递 易错点 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  9. 《从零开始学Swift》学习笔记(Day 20)——函数中参数的传递引用

    原创文章,欢迎转载.转载请注明:关东升的博客 参数的传递引用 类是引用类型,其他的数据类型如整型.浮点型.布尔型.字符.字符串.元组.集合.枚举和结构体全部是值类型. 有的时候就是要将一个值类型参数以 ...

随机推荐

  1. rebbitMQwindows安装及使用

    python中RabbitMQ的使用(安装和简单教程) 1,简介 RabbitMQ(Rabbit Message Queue)是流行的开源消息队列系统,用erlang语言开发.   1.1关键词说明: ...

  2. python字典推导式 - python基础入门(17)

    在昨天的文章中,我们介绍了关于python列表推导式 的使用,字典推导式使用方法其实也类似,也是通过循环和条件判断表达式配合使用,不同的是字典推导式返回值是一个字典,所以整个表达式需要写在{}内部. ...

  3. Centos7安装vim8.0 + YouCompleteMe

    更新yum sudo yum upgrade sduo yum update 下载git sudo yum install git 升级vim以及gcc 升级gcc sudo yum install ...

  4. oracle数据库与其他数据库区别

    本文用的是Oracle 10g数据库,利用PL/SQL Developer的集成开发环境(安装可以自行百度) Oracle数据库  ---> 数据库实例  --->  表空间(逻辑单位)( ...

  5. java日志框架系列(6):logback框架encoder详解

    1.Encoder 1.encoder功能 Encoder 负责两件事,一是把事件转换为字节数组,二是把字节数组写入输出流. 注意:在logback 0.9.19 版之前没有 encoder. 在之前 ...

  6. 数位dp踩坑

    前言 数位DP是什么?以前总觉得这个概念很高大上,最近闲的没事,学了一下发现确实挺神奇的. 从一道简单题说起 hdu 2089 "不要62" 一个数字,如果包含'4'或者'62', ...

  7. C++Primer 5th Chap6 Functions

    局部静态变量,关键字static修饰,即使函数结束执行也不受影响,生存期直到程序终止. java中static的单一存储空间的概念与其或有异曲同工之妙. 函数的形参可以无名,但有名可以使其意义更加清晰 ...

  8. homestead的创建和使用

    1.下载vistualbox和vagrant并安装 2.安装了git的话就在想设置的目录或者文件夹下用git命令执行vagrant box add laravel/homestead,或者用cmd命令 ...

  9. python爬虫框架scrapy 豆瓣实战

    Scrapy 官方介绍是 An open source and collaborative framework for extracting the data you need from websit ...

  10. PAT-1003 Emergency (25 分) 最短路最大点权+求相同cost最短路的数量

    As an emergency rescue team leader of a city, you are given a special map of your country. The map s ...