Go基础系列:惰性数值生成器
惰性数值生成器是指在需要的时候才生成下一个数值,不需要的时候就卡在那。这和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基础系列:惰性数值生成器的更多相关文章
- mysql 开发基础系列6 数值与日期函数
一. 数值函数 1. abs(x) 返回x的绝对值 SELECT ABS(-0.8),ABS(0.8); 2.ceil(x) 返回大于x的最大整数 SELECT CEIL(-0.8),CEIL(0. ...
- Java基础系列-Collector和Collectors
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/10748925.html 一.概述 Collector是专门用来作为Stream的coll ...
- python基础系列教程——Python3.x标准模块库目录
python基础系列教程——Python3.x标准模块库目录 文本 string:通用字符串操作 re:正则表达式操作 difflib:差异计算工具 textwrap:文本填充 unicodedata ...
- Java基础系列-二进制操作
原创文章,转载请标注出处:<Java基础系列-二进制操作> 概述 Java源码中涉及到大量的二进制操作,非常的复杂,但非常的快速. Java二进制表示法 首先了解下二进制,二进制是相对十进 ...
- SpringBoot基础系列-SpringCache使用
原创文章,转载请标注出处:<SpringBoot基础系列-SpringCache使用> 一.概述 SpringCache本身是一个缓存体系的抽象实现,并没有具体的缓存能力,要使用Sprin ...
- JavaScript基础系列
JavaScript基础系列 JavaScript是一种基于对象和事件驱动的客户端脚本语言. JavaScript的注释 // 单行 /**/ 多行注释 JavaScript变量,函数名和操作符都是区 ...
- DAX/PowerBI系列 - 关于时间系列 - 时间相关数值比较 - 用非自带函数
DAX/PowerBI系列 - 关于时间系列 - 时间相关数值比较 - 用非自带函数 文末有彩蛋,解决蛋疼问题 难度: ★★☆☆☆(2星) 适用范围: ★★★☆☆(3星) 概况: 基于时间的汇总可能是 ...
- 基础系列(4)—— C#装箱和拆箱
一 装箱和拆箱的概念 装箱是将值类型转换为引用类型 : 拆箱是将引用类型转换为值类型 : 值类型:包括原类型(Sbyte.Byte.Short.Ushort.Int.Uint.Long.Ulong.C ...
- 夯实Java基础系列9:深入理解Class类和Object类
目录 Java中Class类及用法 Class类原理 如何获得一个Class类对象 使用Class类的对象来生成目标类的实例 Object类 类构造器public Object(); register ...
随机推荐
- Codeforces Round #485 (Div. 2) C. Three displays
Codeforces Round #485 (Div. 2) C. Three displays 题目连接: http://codeforces.com/contest/987/problem/C D ...
- Open/Close Port in Centos
1. Show status /etc/init.d/iptables status 2.Set Port iptables -I INPUT -p tcp --dport 80 -j ACCEPT ...
- mysql中加入海量数据
delimiter // create procedure m() begin declare num int; set num=1; while num < 100000 insert int ...
- noip第30课资料
- 31.Stack
在Java中Stack类表示后进先出(LIFO)的对象堆栈.栈是一种非常常见的数据结构,它采用典型的先进后出的操作方式完成的.每一个栈都包含一个栈顶,每次出栈是将栈顶的数据取出,如下: Stack通过 ...
- Exp3 免杀原理与实践 ——20164325王晓蕊
一.实践基本内容 1.实践目标 (1) 正确使用msf编码器(√),msfvenom生成如jar之类的其他文件(√),veil-evasion(√),加壳工具(√),使用shellcode编程(√) ...
- curl安装和使用
curl可以看作命令行浏览器 1.开启gzip请求 # curl -I http://www.sina.com.cn/ -H Accept-Encoding:gzip,defalte 2.监控网页的响 ...
- [转] KVM I/O slowness on RHEL 6
KVM I/O slowness on RHEL 6 http://www.ilsistemista.net/index.php/virtualization/11-kvm-io-slowness-o ...
- Visual Studio 2017 集成Crystal Report为ASP.NET MVC呈现报表
最近项目需要实现报表功能,平衡各方面的因素,还是使用Crystal Report(水晶报表) 下载较新版本: http://downloads.businessobjects.com/akdlm/cr ...
- Redlock:Redis分布式锁最牛逼的实现
普通实现 说道Redis分布式锁大部分人都会想到:setnx+lua,或者知道set key value px milliseconds nx.后一种方式的核心实现命令如下: - 获取锁(unique ...