好好学习,天天向上

原文:A visual guide to Go Memory Allocator from scratch (Golang) 当我第一次开始试图了解 Go 的内存分配器时,觉得它真令人抓狂。所有的所有都像是神秘的黑盒子。而由于几乎每一个技术魔法都隐藏在抽象之下,因此,你需要层层剥开才能理解它。 因此,在这篇博文中,我们将就做这件事。你想学习关于 Go 内存分配器的所有东西吗?那么,阅读这篇文章算是对了。 物理内存和虚拟内存 每一个内存分配器都需要使用由底层操作系统管理的虚拟内存空间。我们来看看它是如何工作的。 上图为物理内存单元的一个简单说明(并非精确表示) 单个内存
阅读全文 »

原文:HTTP/3: From root to tip HTTP 是为 Web 提供支持的应用层协议。它始于 1991 年所谓的 HTTP/0.9 协议,到 1999 年已经演化为 HTTP/1.1,并为 IETF(Internet Engineering Task Force,互联网工程任务组)所标准化。在很长一段时间里,HTTP/1.1 已经足够好了,但是,Web 不断变化的需求使得我们需要一个更好更合适的协议,因此,在 2015 年,HTTP/2 出现了。最近,据说 IETF 打算提供新的版本 —— HTTP/3。对于一些人而言,这是个惊喜,并由此引发了一些混乱。如果你并没有密切
阅读全文 »

上一个部分解释了如何根据目标获取数据源,接下来,可以对已读图书清单进行分析了。 获取指定年度的数据 因为我们是对某个年度进行分析,所以需要将特定年度的数据筛选出来。这里,先将数据读进 pandas.DataFrame 中: 1 2 3 4 5 6 7 8 import json from pandas import DataFrame, Series path = 'item.json' # read records = [json.loads(line.strip().strip(",")) for line in open(path)] df = DataFrame(record
阅读全文 »

年终惯例是做年度总结,而恰好每年年初都会给自己定一个读书目标。以前总是达标之后心情愉悦便没有然后了,今年突发奇想,想看看过去的一年里,自己都读了什么书,以便有的放矢地安排下一年的读书目标。 需求有了,接下来则是要获取数据了。凑巧我有个习惯,每看一本书会在豆瓣上标记一下。因此,我在豆瓣上的已读清单就是最好的原数据。 创建爬虫 对于爬虫工具的选择,以方便为主,所以我选了scrapy。 安装好 scrapy 后,创建一个名为 book 的项目: 1 scrapy startproject book ## 获取已读图书列表 登陆豆瓣后,找到页面“我读过的书”,就可以看到已阅图书列表了。
阅读全文 »

原文:The Relationship Between Interfaces and Reflection interface 是 Go 中抽象的基本工具之一。在给 interface 赋值时,interface 会存储类型信息。反射(reflection)是一种在运行时检查类型和值信息的方法。 Go 通过 reflect 包实现了反射,该包提供了检查 interface 结构元素甚至是运行时修改值的类型和方法。 在这篇文章中,我希望说明 interface 结构的各个部分与 reflect API 的关系,并最终让 reflect 包的使用更方便! 为 interface 赋值
阅读全文 »

原文:Goroutine Leaks - The Forgotten Sender 介绍 并发编程允许开发者使用多个执行路径来解决问题,并通常用在为提高性能所做的尝试中。但是,并发并不意味着,这些路径并行执行;而是意味着这些路径乱序执行而不是顺序执行。从历史上看,使用标准库或者第三方开发者提供的库可以很方便地进行此类编程。 而在 Go 中,诸如 goroutine 和 channel 这样的并发特性内置在语言和运行时中,以减少或者消除对库对需求。这就造成了用 Go 编写并发程序很容易的错觉。当你决定使用并发时必须很小心,因为如果不正确使用的话,它们就会带来一些独特的副作用或者陷阱。一
阅读全文 »

go 1.12 版本之前,打印 map 得到的结果是不确定的。也就是说,对于同一个 map,每次打印得到的 key 顺序都有可能不一样。 于是,go 1.12 做了一个改动:以 key 的顺序打印 map。也就是说,针对 map,fmt.printValue 会先调用 fmtsort.Sort 方法(位于 src/internal/fmtsort)获取已排序的 key 列表,然后依次打印对应的 value。 下面我们来看看比较规则: * 在适用情况下,nil 的值最小 * 对于所有比较,最开始会比较 key 的类型。如果类型不相同,则返回 a < b(假设 a 是比较函数的第一个参数
阅读全文 »

随着 HTTP 的广泛应用,HTTP/1.0 和 HTTP/1.1 的底层传输模式越来越无法满足对高性能的追求。HTTP/1.0 和 HTTP/1.1 存在以下问题: * 为了实现并发从而减少延迟,HTTP/1.0 和 HTTP/1.1 客户端需要通过多个 TCP 连接发起的多个请求。 * HTTP 头部的重复性和冗余性会引发不必要的网络流量,并引发初始的 TCP 拥塞窗口被快速填满。当多个请求在一个新的 TCP 连接上处理时,上述情况就会导致过多的延迟。 于是,HTTP/2 应运而生。 HTTP/2 支持 HTTP/1.1 的所有核心特性,但是针对 HTTP/1.x 的问题做出了几点改动
阅读全文 »

这是【深入浅出 go xx】系列的第一篇。在该系列中,会对 go 的一些基本特性,从定义到源码进行整理和记录。 希望不要跳票。 什么是 slice? slice 是 Go 的一种基本的数据结构。它在数组之上做了一层封装,相当于动态数组。它持有对底层数组的引用。 因此: * 如果你将一个 slice 赋给另一个 slice,那么,这两个 slice 都会指向同一个数组。 * 如果一个函数的参数包含 slice,那么,对入参 slice 的元素的改动对于该函数的调用者是可见的。类似于传递一个指向底层数组的指针给函数。 每个 slice 都有两个属性:length 和 capacity。前者
阅读全文 »

Go 1.8 为我们带来了 http 服务优雅退出的方式:Server.Shutdown。对于该方法,代码中的解释是: Shutdown 方法会在不干扰任何活跃连接的情况下关闭服务器。首先,它会关闭所有开着的监听器,然后关闭所有空闲连接,接着无限等待所有连接变成空闲状态,最后关闭。 如果提供的 context.Context 对象在关闭完成之前过期了,那么,Shutdown 方法返回该 Context 对象的错误信息。否则,它会将正在关闭的服务器的底层监听器的错误返回(如果有的话)。 一旦调用了 Shutdown 方法,Serve、ListenAndServe 和 ListenAndSe
阅读全文 »