Go语言的Channel遍历方法详解

先来看看基本的定义:

channel是Go语言中的一个核心类型,可以把它看成管道。并发核心单元通过它就可以发送或者接收数据进行通讯,这在一定程度上又进一步降低了编程的难度。

channel是一个数据类型,主要用来解决go程的同步问题以及协程之间数据共享(数据传递)的问题。

(1)channle 本质上是一个数据结构——(队列),数据是先进先出。

(2)具有线程安全机制,多个go程访问时,不需要枷锁,也就是说channel本身是线程安全的。

(3)channel是有类型的,如一个string类型的channel只能存放string类型数据。

Channel遍历主要分为3种:

1)简单的读 data:=<-ch (如果读多次,需要用循环)

var ch8 = make(chan int, 6)
func mm1() {
	for i := 0; i < 10; i++ {
		ch8 <- 8 * i
	}

}
func main() {
	go mm1()
	for i:=0;i<100;i++{
		fmt.Print(<-ch8, "\t")
	}
}

注:

(1)写入的次数与读取的次数需要一致(本例是10);

(2)如果读的次数多于写的次数会发生:fatal error: all goroutines are asleep - deadlock! ,若 在mm1中对ch8进行关闭(执行 close(ch8) ),多于的次数读到的数据为0(数据默认值)。

(3)读的次数少于写的次数,会读取出次数对应的内容,不会报错。

2)断言方式

if value, ok := <-ch; ok == true {

1) 如果写端没有写数据,也没有关闭。<-ch; 会阻塞 ---【重点】

2)如果写端写数据, value 保存 <-ch 读到的数据。 ok 被设置为 true

3)如果写端关闭。 value 为数据类型默认值。ok 被设置为 false

var ch8 = make(chan int, 6)
func mm1() {
	for i := 0; i < 10; i++ {
		ch8 <- 8 * i
	}
	close(ch8)

}
func main() {
	go mm1()
	for {
		if data, ok := <-ch8; ok {
			fmt.Print(data,"\t")
		} else {
			break
		}
	}
}

注:写完之后一定要关闭( 执行:close(ch8) ),否则会出现以下运行结果:

3)通过range方法

for num := range ch {
               }
var ch8 = make(chan int, 6)
func mm1() {
	for i := 0; i < 10; i++ {
		ch8 <- 8 * i
	}
	close(ch8)
}
func main() {

	go mm1()
	for {
		for data := range ch8 {
			fmt.Print(data,"\t")
		}
		break
	}
}

注:写完之后一定要关闭( 执行:close(ch8) ),否则会出现以下运行结果:

特别说明:以上实例都是子go程写,主go程读。如在子go程中写,另一个子go程中读,不管哪种方法,都不会出现以上错误问题。(多次实例验证)

var ch8 = make(chan int, 6)
func mm1() {
	for i := 0; i < 10; i++ {
		ch8 <- 8 * i
	}
	//close(ch8)
}
func mm2() {
	for {
		for data:=range ch8{
			fmt.Print(data,"\t")
		}
	}
}
func main() {
	go mm1()
	go mm2()
	for{
		runtime.GC()
	}
}

总结:

通过以上验证,为了保证程序的健壮性,在设计程序时,最好将channel的读、写分别在子go程中进行。写完数据之后,记得关闭channel。

补充一点:

channel不像文件一样需要经常去关闭,只有当你确实没有任何发送数据了,或者你想显式的结束range循环之类的,才去关闭channel;关闭channel后,无法向channel 再发送数据(引发 panic 错误后导致接收立即返回零值);关闭channel后,可以继续从channel接收数据;对于nil channel,无论收发都会被阻塞。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • Go缓冲channel和非缓冲channel的区别说明

    在看本篇文章前我们需要了解阻塞的概念 在执行过程中暂停,以等待某个条件的触发 ,我们就称之为阻塞 在Go中我们make一个channel有两种方式,分别是有缓冲的和没缓冲的 缓冲channel 即 buffer channel 创建方式为 make(chan TYPE,SIZE) 如 make(chan int,3) 就是创建一个int类型,缓冲大小为3的 channel 非缓冲channel 即 unbuffer channel 创建方式为 make(chan TYPE) 如 make(cha

  • golang开发中channel使用

    channel[通道]是golang的一种重要特性,正是因为channel的存在才使得golang不同于其它语言.channel使得并发编程变得简单容易有趣. channel的概念和语法 一个channel可以理解为一个先进先出的消息队列.channel用来在协程[goroutine]之前传递数据,准确的说,是用来传递数据的所有权.一个设计良好的程序应该确保同一时刻channel里面的数据只会被同一个协程拥有,这样就可以避免并发带来的数据不安全问题[data races]. 正文 channel

  • 详解Golang中Channel的用法

    如果说goroutine是Go语言程序的并发体的话,那么channels则是它们之间的通信机制.一个channel是一个通信机制,它可以让一个goroutine通过它给另一个goroutine发送值信息. 1 创建channel 每个channel都有一个特殊的类型,也就是channels可发送数据的类型.一个可以发送int类型数据 的channel一般写为chan int.使用内置的make函数,如果第二个参数大于0,则表示创建一个带缓存的channel. ch := make(chan in

  • Golang实现Directional Channel(定向通道)

    通道可以是定向的( directional ).在默认情况下,通道将以双向的( bidirectional )形式运作,用户既可以把值放人通道,也可以从通道取出值;但是,通道也可以被限制为只能执行发送操作( send-only )或者只能执行接收操作( receive-only ). 通常可以叫 定向通道 ,也有人叫 单向通道 ,两者其实都是指向这篇短文要讨论的 Directional Channel . 下面直接举例子说明: package onlyChannelTest import ( "

  • Golang的select多路复用及channel使用操作

    看到有个例子实现了一个类似于核弹发射装置,在发射之前还是需要随时能输入终止发射. 这里就可以用到cahnnel 配合select 实现多路复用. select的写法用法有点像switch.但是和switch不同的是,select的一个case代表一个通信操作(在某个channel上进行发送或者接收)并且会包含一些语句组成的一个语句块.现在让我们来实现一下这个核弹发射器 package main import ( "fmt" "time" "os"

  • Go语言的Channel遍历方法详解

    先来看看基本的定义: channel是Go语言中的一个核心类型,可以把它看成管道.并发核心单元通过它就可以发送或者接收数据进行通讯,这在一定程度上又进一步降低了编程的难度. channel是一个数据类型,主要用来解决go程的同步问题以及协程之间数据共享(数据传递)的问题. (1)channle 本质上是一个数据结构--(队列),数据是先进先出. (2)具有线程安全机制,多个go程访问时,不需要枷锁,也就是说channel本身是线程安全的. (3)channel是有类型的,如一个string类型的

  • C语言memset函数使用方法详解

    C语言memset函数使用方法详解 一.函数原形   void *  memset(void*s, int ch,size_t n) 二.函数作用  将以s内存地址为首的连续n个字节的内容置成ch,一般用来对大量结构体和数组进行清零 三.常见错误 1.搞反了 ch 和 n的位置 对char[20]清零,一定是 memset(a,0,20); 2.过度使用memset 3.其实这个错误严格来讲不能算用错memset,但是它经常在使用memset的场合出现 int fun(strucy someth

  • JavaScript实现的DOM树遍历方法详解【二叉DOM树、多叉DOM树】

    本文实例讲述了JavaScript实现的DOM树遍历方法.分享给大家供大家参考,具体如下: 二叉 DOM 树的遍历 function Tree() { var Node = function(key){ this.key = key; this.left = null; this.right = null; } root =null; } 前序遍历 首先访问根结点,然后遍历左子树,最后遍历右子树 Tree.prototype.preOrderTraverse = function(callbac

  • C语言system函数使用方法详解

    目录 函数接口 作用 返回值 测试代码 参数 MODE命令 color命令 函数接口 _DCRTIMP int __cdecl system( _In_opt_z_ char const* _Command ); system函数已经被收录在标准c库中,头文件为<stdlib.h> 作用 执行系统命令调用命令处理器来执行命令. 如果命令是空指针,则该函数只检查是否有命令处理器可以被此函数使用. 命令非空则调用命令的效果取决于系统和库的实现,并可能导致程序以非标准的方式运行或终止. 补充: 执行

  • Go语言HttpRouter路由使用方法详解

    HttpRouter是一个轻量级但却非常高效的multiplexer.手册: https://godoc.org/github.com/julienschmidt/httprouter https://github.com/julienschmidt/httprouter 用法示例 package main import ( "fmt" "github.com/julienschmidt/httprouter" "net/http" "

  • C语言 操作符#与##使用方法详解

    目录 一.# 运算符 二.## 运算符 三.小结 一.# 运算符 # 运算符用于在预处理期将宏参数转换为字符串 # 的转换作用是在预处理期完成的,因此只在宏定义中有效 编译器不知道 # 的转换作用 用法: #define STRING(x) #x printf("%s\n",STRING(Hello World!)); 下面通过一个示例感受一下: test.c: #include <stdio.h> #define STRING(x) #x int main() { pri

  • C语言实现面向对象的方法详解

    目录 1.引言 2.封装 3.继承 4.多态 4.1 虚表和虚指针 4.2 在构造函数中设置vptr 4.3 继承 vtbl 和 重载 vptr 4.4 虚函数调用 4.5 main.c 5.总结 1.引言 面向对象编程(OOP)并不是一种特定的语言或者工具,它只是一种设计方法.设计思想.它表现出来的三个最基本的特性就是封装.继承与多态.很多面向对象的编程语言已经包含这三个特性了,例如 Smalltalk.C++.Java.但是你也可以用几乎所有的编程语言来实现面向对象编程,例如 ANSI-C.

  • C语言qsort函数使用方法详解

    目录 1.qsort函数 1.1qsort函数功能 1.2参数介绍 2.qsort函数功能测试 3.冒泡排序思想模拟实现qsort 1.qsort函数 void qsort (void* base, size_t num, size_t size, int (compar)(const void,const void*)); 1.1qsort函数功能 可以排序任何数据类型 对 所指向的数组元素进行排,使用函数确定顺序. 此函数使用的排序算法通过调用指定函数并指向元素的指针作为参数来比较元素. 该

  • JavaScript实现二叉树的先序、中序及后序遍历方法详解

    本文实例讲述了JavaScript实现二叉树的先序.中序及后序遍历方法.分享给大家供大家参考,具体如下: 之前学数据结构的时候,学了二叉树的先序.中序.后序遍历的方法,并用C语言实现了,下文是用js实现二叉树的3种遍历,并以动画的形式展现出遍历的过程. 整个遍历过程还是采用递归的思想,原理很粗暴也很简单 先序遍历的函数: function preOrder(node){ if(!(node==null)){ divList.push(node); preOrder(node.firstEleme

  • Python编程实现二叉树及七种遍历方法详解

    本文实例讲述了Python实现二叉树及遍历方法.分享给大家供大家参考,具体如下: 介绍: 树是数据结构中非常重要的一种,主要的用途是用来提高查找效率,对于要重复查找的情况效果更佳,如二叉排序树.FP-树.另外可以用来提高编码效率,如哈弗曼树. 代码: 用Python实现树的构造和几种遍历算法,虽然不难,不过还是把代码作了一下整理总结.实现功能: ① 树的构造 ② 递归实现先序遍历.中序遍历.后序遍历 ③ 堆栈实现先序遍历.中序遍历.后序遍历 ④ 队列实现层次遍历 #coding=utf-8 cl

随机推荐