惰性数值生成器是指在需要的时候才生成下一个数值,不需要的时候就卡在那。这和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. CodeSampler DX9 Full-screen initialization

    D3D新手,请轻拍. 最近在学CodeSampler上的DX9范例.编译环境是VS2012.搭编译环境用了一两天,另行开文吐槽(有时间的话). 本文讲讲Full-screen initializati ...

  2. Adnroid开发环境搭建(四步搞定)

    新手博友,多多关照 下面给大家介绍JDK Eclipse AndroidSDK ADT环境搭建,安装教程 第一步.安装JDK: 第二步.安装Eclipse: 第三步.下载并安装AndroidSDK: ...

  3. CSS伪类的理解

    因为之前一直对css伪类没有过多的了解,在网上看到一段css代码,不能理解 a:hover span.title{ color:red; ......... } 现通过查询css手册,其实css伪类只 ...

  4. 针对zstack虚拟机导出的问题的解决办法!

    1. nfs 首先定位image所在位置: 云主机--〉云盘操作--〉配置信息--〉更多信息--安装路径 /opt/zstack/nfsprimarystorage/prim-aab63dc6284f ...

  5. ubuntu hadoop环境搭建

    安装Ubuntu系统:这个自行安装 下载jdk:我下的是1.8.0_141d的,下载好后在usr/lib下新建一个jvm的文件夹用来存放Java的文件,下载好的jdk可以在其他地方解压或者jvm里面解 ...

  6. 03 of learning python

    01 input输入的是str类型 如果输入的是数字的话,要记得强制转换一下! 02 isdigit() 这个方法是用来检测字符串是否全部由数字组成 str.isdigit() 如果字符串只包含数字则 ...

  7. C++ 引用、构造函数、移动语义

    1.引用 C++中的引用主要用作函数的形参,接近于const指针,必须在创建时初始化. 以Person类为例,如下: Person p;                          //调用P的 ...

  8. 常用maven仓库

    常用Maven仓库网址:http://mvnrepository.com/http://search.maven.org/http://repository.sonatype.org/content/ ...

  9. [转] Snapshotting with libvirt for qcow2 images

    http://kashyapc.com/2011/10/04/snapshotting-with-libvirt-for-qcow2-images/ Libvirt 0.9.6 was recentl ...

  10. ZKWeb网页框架2.2正式发布

    2.2.0更新的内容有 重构依赖注入容器 使用无锁算法 (可能导致不兼容) 使用 ContainerFactoryData 创建实例 (可能导致不兼容) 删除静态的 ContainerFactoryC ...