惰性数值生成器是指在需要的时候才生成下一个数值,不需要的时候就卡在那。这和python的列表推导表达式类似。惰性生成器的好处是不会一次性将全部结果返回或放进内存,而是每次只返回一个,这样不会在某一时刻大量占用内存和其它资源。

比如,要生成10W个数值,如果要迭代这10W个数值,有两种方法。第一种方法是将10W个数值全部生成好放进一个数组(或其它数据结构),然后再去数组中取数据。第二种方法是迭代到哪个数值的时候临时去生成这个数值。它们的区别是显然的:第一种方法会占用大量内存,且速度有可能会很慢,第二种方法每次只占用一个数值的内存空间,用完就丢了。

下面是一个不算完美的惰性数值生成器示例:

package main

import (
"fmt"
) func generateNums(nums chan int) {
num := 0
go func() {
for {
num++
nums <- num
}
}()
} func getNums(nums chan int) int {
return <-nums
} func main() {
nums := make(chan int)
generatenums(nums)
for i := 0; i < 10; i++ {
fmt.Println(getnums(nums))
}
}

其中generateNums()函数是惰性数值生成器,它使用一个nums channel作为参数,每次生成的数值都会放进这个channel中。

getNums()函数是取出存入nums channel中的数并返回。

理论上一切都很简单,只要在需要的地方调用generateNums()函数即可。但问题在于如果多个地方调用generateNums(),各个地方的nums通道将互相影响。所以,应该改进一下,让generateNums()自带属于自己的nums通道,而不是多个generateNums()共享一个nums通道。

func generateNums(nums chan int) {}
|
\|/
func generateNums(){
nums := make(chan int)
}

因为通道私有了,要想从这个通道中取数据,需要将这个通道作为返回值:

func generateNums() chan int{
nums := make(chan int)
...
return nums
}

这样每次调用generateNums()就取得了它的数值生成器通道:

nums := generateNums()

下面是改良后的惰性数值生成器:

package main

import (
"fmt"
) func generatenums() chan int {
nums := make(chan int)
num := 0
go func() {
for {
num++
nums <- num
}
}()
return nums
} func getnums(nums chan int) int {
return <-nums
} func main() {
nums := generatenums()
for i := 0; i < 10; i++ {
fmt.Println(getnums(nums))
}
}

Go基础系列:惰性数值生成器的更多相关文章

  1. mysql 开发基础系列6 数值与日期函数

    一. 数值函数 1.  abs(x) 返回x的绝对值 SELECT ABS(-0.8),ABS(0.8); 2.ceil(x) 返回大于x的最大整数 SELECT CEIL(-0.8),CEIL(0. ...

  2. Java基础系列-Collector和Collectors

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/10748925.html 一.概述 Collector是专门用来作为Stream的coll ...

  3. python基础系列教程——Python3.x标准模块库目录

    python基础系列教程——Python3.x标准模块库目录 文本 string:通用字符串操作 re:正则表达式操作 difflib:差异计算工具 textwrap:文本填充 unicodedata ...

  4. Java基础系列-二进制操作

    原创文章,转载请标注出处:<Java基础系列-二进制操作> 概述 Java源码中涉及到大量的二进制操作,非常的复杂,但非常的快速. Java二进制表示法 首先了解下二进制,二进制是相对十进 ...

  5. SpringBoot基础系列-SpringCache使用

    原创文章,转载请标注出处:<SpringBoot基础系列-SpringCache使用> 一.概述 SpringCache本身是一个缓存体系的抽象实现,并没有具体的缓存能力,要使用Sprin ...

  6. JavaScript基础系列

    JavaScript基础系列 JavaScript是一种基于对象和事件驱动的客户端脚本语言. JavaScript的注释 // 单行 /**/ 多行注释 JavaScript变量,函数名和操作符都是区 ...

  7. DAX/PowerBI系列 - 关于时间系列 - 时间相关数值比较 - 用非自带函数

    DAX/PowerBI系列 - 关于时间系列 - 时间相关数值比较 - 用非自带函数 文末有彩蛋,解决蛋疼问题 难度: ★★☆☆☆(2星) 适用范围: ★★★☆☆(3星) 概况: 基于时间的汇总可能是 ...

  8. 基础系列(4)—— C#装箱和拆箱

    一 装箱和拆箱的概念 装箱是将值类型转换为引用类型 : 拆箱是将引用类型转换为值类型 : 值类型:包括原类型(Sbyte.Byte.Short.Ushort.Int.Uint.Long.Ulong.C ...

  9. 夯实Java基础系列9:深入理解Class类和Object类

    目录 Java中Class类及用法 Class类原理 如何获得一个Class类对象 使用Class类的对象来生成目标类的实例 Object类 类构造器public Object(); register ...

随机推荐

  1. python pandas.DataFrame.append

    1.使用append首先要注意的是,你要合并两个DataFrame的columns即列名是否是相同的,不相同的就会报错. 2.我们会发现DataFrame的列名是不能够重复的,而行名(index)是可 ...

  2. shell脚本学习-分支结构

    跟着RUNOOB网站的教程学习的笔记 if语法格式 if condition then command1 command2 ... commandN fi 写成一行(使用于终端命令提示符): ]; t ...

  3. mycat跟踪分析

    mycat版本1.6 192.168.5.66 从 192.168.5.67主 一个user表 验证主从 log4j2修改日志level为debug schema.xml配置 启动服务,打开日志tai ...

  4. 2018-04-10 我的GitHub诞生的日子,欢迎大家吐槽批评

    我的GitHub,诞生的日子,欢迎大家吐槽与批评,嘻嘻 首先是自己想刷一下LeetCode上的代码,其次创建了自己的读书笔记以及面试经验与教训 下边是仓库的Git链接,欢迎大家的批评与修正,谢谢: L ...

  5. Numpy1

    列表转n维数组ndarray import numpy as np list=[1,2,3,4] n=np.array(list) random模块生成ndarray n1=np.random.ran ...

  6. 前端 高级 (二十五)vue2.0项目实战一 配置简要说明、代码简要说明、Import/Export、轮播和列表例子

    一.启动服务自动打开浏览器运行 二.配置简要说明 1.node_modules 安装好的依赖文件,中间件等,所在位置 2.package.jason 配置当前项目要安装的中间件和依赖文件 { &quo ...

  7. python yield 关键字

    最近看代码看到python里面的yield关键字,和我之前接触的语言好像都没有来着,我就查了查它的含义,大概理解如下: >>> def createGenerator(): ... ...

  8. TCP/IP(八)之总结TCP/IP四层模型

    阅读目录(Content) 一.TCP/IP参考模型概述 1.1.TCP/IP参考模型的层次结构 二.TCP/IP四层功能概述 2.1.主机到网络层 2.2.网络互连层 2.3.传输层 2.3.应用层 ...

  9. CTF中文件包含的一些技巧

    i春秋作家:lem0n 原文来自:浅谈内存取证 0x00 前言 网络攻击内存化和网络犯罪隐遁化,使部分关键数字证据只存在于物理内存或暂存于页面交换文件中,这使得传统的基于文件系统的计算机取证不能有效应 ...

  10. [Postman]Cookies(12)

    Postman的本机应用程序提供  MANAGE COOKIES  模式,允许您编辑与每个域关联的Cookie. 前往cookie经理 要打开MANAGE COOKIES模式,请单击“ 发送”按钮下的 ...