知识分为三类:发明一个东西的知识,生产一个东西的知识,使用一个东西的知识。
— 于尔根・雷恩 《人类知识演化史》
全部内容的时间索引 —— 长文、外链摘藏与只言片语,无论是否上首页,都在此完整收录。
知识分为三类:发明一个东西的知识,生产一个东西的知识,使用一个东西的知识。
— 于尔根・雷恩 《人类知识演化史》
想问题的时候,“大概一想” 是最爽的,又轻松,又快乐。如果仔细想,一来费脑子,二来可能会发现一开始想错了,又不轻松,又不快乐。但如果你希望自己能把事情想得清楚一点,有一些做起来并不困难的基本方法。当然,费脑子可能还是会费脑子的。
比如,你觉得某某是错的,不要到此为止,而是更进一步想清楚:具体什么地方错了?为什么是错的?如果你觉得某某是坏的,具体什么地方坏?为什么是坏的?如果你觉得某某造谣,具体造了什么谣?说了什么谎言?想问题的时候,尽可能用包含 “因为” 和 “所以” 的句子来给出判断的理由。如果你的理由类似 “因为某某 XX,所以某某是坏的”,那么再想一想是不是对于任何事物,只要 XX,就是坏的?如果不是,为什么某某 XX 就是坏的?
能坚持这样做,就超过大多数人了。更严谨的思维未必能帮你赚钱,但可以少糊里糊涂地随波逐流,少受蛊惑,少受骗。这当然不会很容易,我也做不到在每个问题上都能避免 “大概一想”。
— tombkeeper 微博
类似于必读书目的书单,那些值得反复阅读、常读常新的技术博客,也应该被系统地整理成一份精选集合。 先开个坑,后续逐步填充内容 百度 C++ 工程师的那些极限优化(内存篇) 百度 C++ 工程师的那些极限优化(并发篇)
What we want is a machine that can learn from experience.
— Alan Turing
吉姆・罗恩的一个观点:失败很少是轰轰烈烈地到来的,它不会敲门,而是悄悄溜进来。 你有没有过这样的经历:今天有点累,就不晨读了吧;健身房下周再去,反正卡还有一年有效期。 每一个决定单独拿出来看,都合情合理。 但这些小决定叠加起来,日复一日,就把你和你想成为的那个人隔开了。 这就是罗恩说的沉默的小偷,它…
养成费米估算的习惯,主动查证关键数据,并运用上下限分析法。我注意到许多我认识的最聪明的人都会这样做:他们不会轻信任何说辞,而是自行验证其合理性。例如,听到某个事实时,他们会亲自查证以确保属实 —— 因为人们引用的内容常常存在虚假或片面性。
大多数人根本不这样做 —— 他们不进行 “量化思考”,结果很容易上当受骗。推特上时不时会流行这样的梗:“如果伊隆把造火箭的钱分给每个美国人,等等” 这类言论会疯传,就是因为人们没有算账。
— Nabeel S. Qureshi
费米估算由物理学家费米提出,他曾在课堂上问学生:“芝加哥有多少钢琴调音师?”—— 没人能查数据,但通过拆解估算,答案数量级和实际值高度吻合 。
费米估算的原理:
1970 年,波音就已经引入了 CAD 电脑画图。但交付给下个部门的时候,却是把结果打印出来,让下一个部门的人用眼睛读、用脑子理解、再靠脑子去执行。 星巴克的咖啡师做咖啡的速度提高 100 倍,星巴克未必能多赚很多钱。星巴克的瓶颈不在做咖啡的速度,在于客流、选址、供应链管理。 同理,你们公司的瓶颈,…
我在那些爸爸们中间坐了一会儿,但很快就烦了他们。全部的爸爸都是带着女儿来参加这个可爱的小小宴会的,但他们都在讨论股票的事儿——他们不知道怎么和自己的孩子说话,更不知道怎么和孩子的朋友们说话。 别人认为你应该达到什么造诣,但你没有责任来满足他们的想当然。我没有责任成为他们指望我成为的东西。错误是他们犯…
当我发现圣诞老人并不存在时,我没有感到难过,反而释然了,原来有一个更简单的说法可以解释为什么全世界那么多孩子会在同一天夜里收到礼物。之前的故事太复杂了,我快想不透了
这是我从我父亲那里学来的:不尊重任何权威;不要管话是谁说的,但要关注他说的条件是什么,结论又是什么,然后问自己:“这合理吗”
基于我划线最密集、最认同的这 3 本书的核心主张,帮我找出与其观点完全对立、批判最狠的 5 本硬核书籍,给我做一次认知压力测试。 假设我以当前的阅读结构和速率继续读 5 年,推演那时的我会变成什么样的人,会形成哪些固化偏见,产生哪些知识盲区,错过哪些真正重要的问题,并指出现在必须立刻插入哪 5 本反…
定义你的,不是你的本质,而是你的所作所为。
— 《蝙蝠侠》
一件事情,在大多数时候是没有确定性答案的。认知不是从天上掉下来的,它是靠人不断推演、争论、交流,一点一点磨出来的——这个过程不能省略,因为这个过程就是人本身。 如果认知直接由 AI 给到,且不论它是否全面、是否带着批判性,单是中间那段思考的缺席,就足以让主体性一寸一寸地退场,最后沦为珍妮机前面那个等…
AI 的热潮确实让我想起早期低代码和无代码工具的突破。我不怀疑 AI 能成为开发者的有用工具,我知道有些任务它能作为更好的工具来辅助完成。但这些论点总让我再次思考偶然复杂性与本质复杂性的问题。 布鲁克斯在《没有银弹》一文中探讨了新工具对开发者生产力的影响。要像程序员一样思考,你必须理解现实世界的复杂…
养成习惯的好处是,在行动时,不必再进行内心的权衡。
不再消耗能量去思考是否要做这件事。
你只管去做。
每个人都害羞。
其他人在等你做自我介绍;
他们在等你给他们发邮件;
他们在等你
约他们出去。
基于 Astro,从零重新实现
在这样高密度、高复杂性的任务上,如果想 scale up, 那人在其中的占比一定要是少的,人只能是驾驭,否则这个效率就会很低,我们就做不出最有生产力最好的东西。 要改变视角,工作应该改造成以 ai 为中心,而非继续以人为中心。 不要想模型做不到,而且想模型能做到,我应该怎么配合模型做到。 如果一个…
当 int/long/float/指针/std::string 作为 std::unordered_map 的 key 时,C++ 底层是如何计算 hash 值的?
gcc/clang 作为使用最多的两种编译器和标准库,它们在这个问题的实现上略有差异。本文将基于二者的源码进行对比分析。
一方面,我越来越擅长自学,也养成了独立思考的能力;另一方面,我变得孤僻,不善与人建立连接。面对人群,我总是局促不安,不知如何表达真实的自己;我害怕袒露想法,总觉得无人理解,也无人愿意理解。 人必须与外部世界建立连接,而表达,就是这场连接中的第一道桥梁。 我才明白,表达不是可有可无的能力,而是一门人生…
如果你希望存储一段信息,让 100 年后的人也能访问,要怎么做? 三体中有类似的想法:如果人类灭亡,最好的保存文明的方式是什么?答案是:“刻在石头上” 但在一百年的时间尺度上,文章作者认为 GitHub 是存储信息的最好方式: Github 已经是全人类的互联网基础设施 Git 能保存所有的 com…
tk 教主分享在微博上的文章:"粉丝群有人问有没有关于怎么带团队的书。我觉得把《怎样当好一名师长》看明白就够了。这也是我非常推崇的一篇文章。" 要勤快:应该自己干的事情一定要亲自过问,亲自动手。 要摸清上级的意图:对上级的意图要真正理解,真正融会贯通,真正认识自己所领受的任务在战役、战斗全局中的地位…
要锻炼出创造性的身体,去看电影、听音乐会、去美术馆、看别人的建筑,然后要有想做得比他们更好的意愿,超越前人的勇气,体力衰退了,竞争意识就会变弱。没有了创造性的身体,竞争意识就没了。这两个是一回事,要同时锻炼身体和意志。
— 安藤忠雄 《武士建筑师》
我捐出了所有来自苹果的财富,因为财富和权力并非我的追求。我享受生活的乐趣——在我的出生地圣何塞,我资助了许多重要的博物馆和艺术团体,他们以我的名字命名了一条街道以示认可。如今我从事公开演讲并成为行业顶尖,虽然不清楚具体资产数额,但经过 20 年的演讲事业,可能积累了约 1000 万美元和几处房产。我从不寻找任何避税手段,通过劳动获得的收入缴纳约 55%的综合税负。我是世界上最快乐的人。对我而言,生活从来不是关于成就,而是关于快乐,那正是笑容减去愁容的简单公式。这些人生理念在我 18 到 20 岁时就已形成,而我始终坚守至今。
— 沃兹尼亚克
最近看了《成为乔布斯》这本书以及听了播客半拿铁的《苹果简史》。对沃兹的印象就是他和乔布斯最开始的组合就是天使+魔鬼,沃兹是毫无疑问的赤子。沃兹的这个留言更加印证了这个印象。
今天恰好是 woz 的生日,看到了他在论坛上的留言,再次感叹他的人生态度。
我们做任何决定,最终都有可能会后悔会遗憾,但是面对多个选择时,我们应该选择让自己后悔或者遗憾最少的那个。
— 贝索斯
股市是世界上最可爱的东西。对于股市你可以随便怎么想,怎么想都可以,甚至觉得”川大智胜”和川普有关系都可以。
一切观点、一切想法都可以掏钱验证。如果你是对的,那就不光是对的,还能赚钱。所以如果你这么坚定地相信,就没道理不掏钱。除非,你其实也没那么相信。
社会是一个周期更长的股市。每个人最终都会在这个股市里得到和自己的想法相匹配的回报,一切想法也最终都会变成收益或亏损。而且社会这个股市是由不得你不掏钱的,退不了,缩不了,怂不了。 不光是钱,你的整个人生都会被投入进去。所以收获的也不光是钱,是你整个人生的悲喜荣哀。
所以,你可以随便怎么想,怎么舒服怎么想,或者,认真地思考自己的每一个判断,每一个决定,想清楚自己要的到底是简单、爽,还是有更想要的东西。
— tombkeeper
C++17 中引入了 std::any,可以非常方便地将任意类型的变量放到其中,做到安全的类型擦除。然而万物皆有代价,这种灵活性背后必然伴随着性能取舍。
std::any 的实现本身也并不复杂,本文将基于 libstd++ 标准库源码 深入解析其实现机制与性能开销。
我们在使用 C++ 的时候,有时会需要在类的内部获取自身的 shared_ptr,这就会用到 std::enable_shared_from_this。在实际使用过程中,std::enable_shared_from_this 有三个陷阱需要注意:
我们有这么一段业务代码,在 Gin 的 API Handler 中,开了一个子 goroutine 写 DB,代码大概是这样:
几乎世界上每个 Golang 程序员都踩过一遍 for 循环变量的坑,而这个坑的解决方案已经作为实验特性加入到了 Go 1.21 中,并且有望在 Go 1.22 中完全开放。
Bigcache 是用 Golang 实现的本地内存缓存的开源库,主打的就是可缓存数据量大,查询速度快。 在其官方的介绍文章 《Writing a very fast cache service with millions of entries in Go》 一文中,明确提出了 bigcache 的设计目标:
最近发现 Golang 标准库竟然自带了 varint 的实现,代码位置在 encoding/binary/varint.go,这个跟protobuf里面的varint实现基本是一致的。刚好借助 golang 标准库的 varint 源码,我们来系统地学习和梳理下 varint。
sync.Pool 是 Golang 内置的对象池技术,可用于缓存临时对象,以缓解因频繁建立临时对象带来的性能损耗以及对 GC 带来的压力。
问题是这样的:我在代码里面调用了 os.Chmod("test.txt", 777),希望把该文件的读写及执行权限对所有用户开放。
我们在开发 HTTP Server 的时候,经常有对接口内容做缓存的需求。例如,对于某些热点内容,我们希望做 1 分钟内的缓存。短期内缓存相同内容不会对业务造成实质影响,同时也会降低系统的整体负载。
「优雅终止」指的是当服务需要下线或者重启时,通过一些措施和手段,一方面能够让其他服务尽快的感知到当前服务的下线,另一方面也尽量减小对当前正在处理请求的影响。优雅终止可提升服务的高可用,减少下线造成的服务抖动,提升服务稳定性和用户体验。
一致性 Hash 常用于缓解分布式缓存系统扩缩容节点时造成的缓存大量失效的问题。一致性 Hash 与其说是一种 Hash 算法,其实更像是一种负载均衡策略。
sync.Cond 条件变量是 Golang 标准库 sync 包中的一个常用类。sync.Cond 往往被用在一个或一组 goroutine 等待某个条件成立后唤醒这样的场景,例如常见的生产者消费者场景。
sync.WaitGroup 是 Golang 中常用的并发措施,我们可以用它来等待一批 Goroutine 结束。
依赖注入是一个经典的设计模式,可有效地解决项目中复杂的对象依赖关系。
本文将基于 Golang 源码对 Timer 的底层实现进行深度剖析。主要包含以下内容:
time.Sleep 的实现细节,Golang 如何实现 Goroutine 的休眠。注:本文基于 go-1.13 源码进行分析,而在 go 的 1.14 版本中,关于定时器的实现略有一些改变,以后会再专门写一篇文章进行分析。
Elasticsearch 是一个分布式搜索引擎,底层基于 Lucene 实现。Elasticsearch 屏蔽了 Lucene 的底层细节,提供了分布式特性,同时对外提供了 Restful API。Elasticsearch 以其易用性迅速赢得了许多用户,被用在网站搜索、日志分析等诸多方面。由于 ES 强大的横向扩展能力,甚至很多人也会直接把 ES 当做 NoSQL 来用。
本文整理和记录下自己在运营 个人博客 以及公众号时常使用到的一些工具。主要包含以下方面:
channel 是 Golang 中一个非常重要的特性,也是 Golang CSP 并发模型的一个重要体现。简单来说就是,goroutine 之间可以通过 channel 进行通信。
channel 在 Golang 如此重要,在代码中使用频率非常高,以至于不得不好奇其内部实现。本文将基于 go 1.13 的源码,分析 channel 的内部实现原理。
定时器是网络框架中非常重要的组成部分,往往可以利用定时器做一些超时事件的判断或者定时清理任务等。
本文主要介绍 Filebeat 7.5 版本中 Log 相关的各个配置项的含义以及其应用场景。
一般情况下,我们使用 log input 的方式如下,只需要指定一系列 paths 即可。
filebeat.inputs:
- type: log
paths:
- /var/log/messages
- /var/log/*.log
但其实除了基本的 paths 配置外,log input 还有大概十几个配置项需要我们关注。
这些配置项或多或少都会影响到 Filebeat 的使用方式以及性能。虽然其默认值基本足够日常使用,但是还是需要深刻理解每个配置项背后的含义,这样才能够对其完全把控。
同时,在 filebeat 的日常线上运维中,也会涉及到这些配置参数的调节。
Redis 作为一个单线程高性能的内存缓存 Server 而被人熟知。作为一个典型的 Reactor 式网络应用,Redis 能够达到如此高的性能,必然要依靠足够可靠的事件循环库。
Redis 内置了一个高性能事件循环器,叫做 AE。其定义和实现可以在 ae*.h/cpp 这些文件中找到。
AE 本身就是 Redis 的一部分,所以整体设计原则就是够用就行。也正因为这个背景,AE 的代码才可以简短干净,非常适合阅读和学习。
本文将基于 Redis 5.0.6 的源码分析下其事件循环器 (AE) 的实现原理。
同时本人也提供了一个 Redis 注释版,用以辅助理解 Redis 的源码。
Filebeat 是使用 Golang 实现的轻量型日志采集器,也是 Elasticsearch stack 里面的一员。本质上是一个 agent,可以安装在各个节点上,根据配置读取对应位置的日志,并上报到相应的地方去。
Filebeat 的可靠性很强,可以保证日志 At least once 的上报,同时也考虑了日志搜集中的各类问题,例如日志断点续读、文件名更改、日志 Truncated 等。
Filebeat 并不依赖于 Elasticsearch,可以单独存在。我们可以单独使用 Filebeat 进行日志的上报和搜集。filebeat 内置了常用的 Output 组件, 例如 kafka、Elasticsearch、redis 等。出于调试考虑,也可以输出到 console 和 file。我们可以利用现有的 Output 组件,将日志进行上报。
当然,我们也可以自定义 Output 组件,让 Filebeat 将日志转发到我们想要的地方。
filebeat 其实是 elastic/beats 的一员,除了 filebeat 外,还有 HeartBeat、PacketBeat。这些 beat 的实现都是基于 libbeat 框架。
uber 在 Github 上开源了一套用于服务限流的 go 语言库 ratelimit, 该组件基于 Leaky Bucket(漏桶) 实现。
我在之前写过一篇 《Golang 限流器 time/rate 实现剖析》,分析了 Golang 标准库中基于 Token Bucket 实现限流组件的 time/rate 原理,同时也讲了限流的一些背景。
相比于 TokenBucket 中,只要桶内还有剩余令牌,调用方就可以一直消费的策略。Leaky Bucket 相对来说更加严格,调用方只能严格按照预定的间隔顺序进行消费调用。(虽然 uber-go 对这个限制也做了一些优化,具体可以看下文详解)
还是老规矩,在正式讲其实现之前,我们先看下 ratelimit 的使用方法。
限流器是微服务中必不缺少的一环,可以起到保护下游服务,防止服务过载等作用。上一篇文章 《Golang 限流器 time/rate 使用介绍》 简单介绍了 time/rate 的使用方法,本文则着重分析下其实现原理。建议在正式阅读本文之前,先阅读下上一篇文章。
上一篇文章讲到,time/rate 是基于 Token Bucket(令牌桶) 算法实现的限流。本文将会基于源码,深入剖析下 Golang 是如何实现 Token Bucket 的。其代码也非常简洁,去除注释后,也就 200 行左右的代码量。
同时,我也提供了 time/rate 注释版,辅助大家理解该组件的实现。
本主题为系列文章,分上下两篇。本文主要介绍
time/rate的具体使用方法,另外一篇文章 《Golang 限流器 time/rate 实现剖析》 则着重介绍其内部实现原理。
限流器是后台服务中的非常重要的组件,可以用来限制请求速率,保护服务,以免服务过载。 限流器的实现方法有很多种,例如滑动窗口法、Token Bucket、Leaky Bucket 等。
其实 Golang 标准库中就自带了限流算法的实现,即 golang.org/x/time/rate。该限流器是基于 Token Bucket (令牌桶) 实现的。
简单来说,令牌桶就是想象有一个固定大小的桶,系统会以恒定速率向桶中放 Token,桶满则暂时不放。 而用户则从桶中取 Token,如果有剩余 Token 就可以一直取。如果没有剩余 Token,则需要等到系统中被放置了 Token 才行。
libco 是微信后台开发和使用的协程库,同时也是极少数的直接将 C/C++ 协程运用到如此大规模的生产环境中的案例。
在 《云风 coroutine 协程库源码分析》 中,介绍了有栈协程的实现原理。相比云风的 coroutine,libco 在性能上号称可以调度千万级协程。 从使用上来说,libco 不仅提供了一套类 pthread 的协程通信机制,同时可以零改造地将三方库的阻塞 IO 调用进行协程化。
本文将从源码角度着重分析 libco 的高效之道。
在正式阅读本文之前,如果对有栈协程的实现原理不是特别了解,建议提前阅读 《云风 coroutine 协程库源码分析》。
同时,我也提供了 libco 注释版,用以辅助理解 libco 的源码
C++11 中推出了三种智能指针,unique_ptr、shared_ptr 和 weak_ptr,同时也将 auto_ptr 置为废弃 (deprecated)。
最近在写 C++ 时,有这样一个代码需求:在 lambda 中,将一个捕获参数 move 给另外一个变量。 看似一个很简单常规的操作,然而这个 move 动作却没有生效。
具体代码如下:
std::vector<int> vec = {1,2,3};
auto func = [=](){
auto vec2 = std::move(vec);
std::cout << vec.size() << std::endl; // 输出:3
std::cout << vec2.size() << std::endl; // 输出:3
};
代码可在 wandbox 运行。
我们期望的是,将对变量 vec 调用 std::move 后,数据将会移动至变量 vec2, 此时 vec 里面应该没有数据了。但是通过打印 vec.size() 发现 vec 中的数据并没有按预期移走。
这也就意味着,构造 vec2 时并没有按预期调用移动构造函数,而是调用了拷贝构造函数。
为什么会造成这个问题呢, 我们需要结合 std::move 和 lambda 的原理看下。(最终的解决方案可以直接看 这里)
随着 Golang 的兴起,协程尤其是有栈协程 (stackful coroutine) 越来越受到程序员的关注。协程几乎成了程序员的一套必备技能。
云风实现了一套 C 语言的协程库,整体背景可以参考其 博客。
这个协程库非常轻量级,一共也才 200 多行代码,使用上更贴近于 lua 的写法(众所周知,云风是知名的 lua 粉)。整体基于 ucontext 和共享栈模型实现了有栈协程,代码质量毋庸置疑,本文将详细剖析该协程库的实现原理。
同时,我也提供了 coroutine 注释版,辅助大家理解 coroutine 的代码。
微信云支付 Android 智能 POS 使用 WebSocket 实现了用户订单的实时推送。即,顾客在扫描了门店的付款码,客户端会随即进行语音播报和打印等动作。
在进行 Linux 网络编程开发的时候,免不了会涉及到 IO 模型的讨论。《Unix 网络编程》一书中提到的几种 IO 模型,我们在开发过程中,讨论最多的应该就是三种: 阻塞 IO、 非阻塞 IO 以及 异步 IO。
本文试图理清楚几种 IO 模型的根本性区别,同时分析了为什么在 Linux 网络编程中最好要用非阻塞式 IO。
在客户端开发中,往往会有一些功能对时间要求比较严格,客户端需要获取到当前最准确的时间。但由于客户端环境多种多样,我们无法保证直接在客户端设备上获取到的时间是最准确的时间。 对于某些问题设备来说,设备时间与比当前实际的时间差了几个小时,甚至几天的情况都存在。倘若某功能依赖于当前时间,而客户端所提供的时间不准,就往往会给客户造成一些困扰。
那么,客户端如何能够获取到当前最准确的时间呢?
muduo 是 陈硕 大神个人开发的 C++ 的 TCP 网络编程库。muduo 基于 Reactor 模式实现,Reactor 模式也是目前大多数 Linux 端高性能网络编程框架和网络应用所选择的主要架构,例如 Redis 和 Java 的 Netty 库等。
陈硕的《Linux 多线程服务器端编程》一书对 muduo 整个架构进行了非常详尽的介绍和分析,可以说是学习 muduo 源码和设计理念最好的资料了。
而本文则主要是从源码角度辅助理解整个 muduo 的实现,同时也姑且算是对 muduo 的一个小小的补充。
同时我也提供了一个 muduo 注释版,用以辅助理解 muduo 的源码。
最近我用 Golang 开发了一个可以将数据库每张表的各个列信息转化成文档的小工具。开发的缘由是因为写后端时,经常需要为数据库写说明文档,对于稍微有些规模的项目来说,就动辄几十张上百张数据表,开发人员在文档中不断的写各个列的列名、类型、描述实在是无聊、枯燥和苦不堪言。所以就有了这个小工具的诞生。
项目地址在 这里
ClassViewer 是我最近开发的一个用于展示 jvm class 字节码的小工具。它是一个单纯的静态网页,完全使用浏览器端的 Javascript 开发。之所以开发这款工具,是因为我在开发 ToyJVM 的时候,需要常常校验 class 文件某一部分的字节码, 所以如果一款工具能够很方便的显示 class 文件各个部分的信息和字节码,对于 ToyJVM 的开发将会是一个非常大的帮助。
在开始写代码之前调研了一些类似的产品,主要有 jdk 自带的 javap、国外的 Java-Class-Viewer 以及国人开发的 classpy,它们都是非常不错的 class 文件分析工具,但是也存在着一些算不上缺陷的小问题。所以最终还是决定自己写一个适合自己小工具,同时也加深下 class 结构的理解。
在调研了目前的产品后,我也更加清晰了自己的目标。首先它的受众应该是有兴趣研究 jvm 的程序员,而它应该有这些特性:
最终实现出来的工具是这样的:
4 月 9 号,在武汉参加了人生第一次半程马拉松,风里雨里的 21.0975 公里。虽然已时隔一周,但想到那天一路的奔跑、疲惫、欣喜,还是想记记这半马的流水账。
BloomFilter(布隆过滤器)是一种可以高效地判断元素是否在某个集合中的算法。
在很多日常场景中,都大量存在着布隆过滤器的应用。例如:检查单词是否拼写正确、网络爬虫的 URL 去重、黑名单检验,微博中昵称不能重复的检测等。
前两天把实验室的一台旧台式机装上了 Ubuntu Server,打算当作测试服务器使用着玩。 装上之后意识到一个严重的问题:实验室电脑连接外网时候需要打开浏览器输入学号进行认证。
在此博客之前,我其实也用过新浪博客、CSDN、博客园,作为个人博客的载体,但对每个博客都并不是特别的满意。原因大概有下面几条:
目前该博客是使用 hexo + Next 主题 + Github 进行搭建。 事实上,当开始接触使用 hexo 时,我觉得满足了我对博客的诸多要求。我对它的为程序员而生、高度可定制性非常喜欢。而且,如有机会,可以自己写出满意的主题使用。
我很喜欢这种巧妙的分类框架 —— 我们平时太容易把相似的东西混为一谈,而一个好的分类能帮我们把事情本身理清楚。
比如《没有银弹》里把复杂性分为「偶然复杂性」和「本质复杂性」。
再比如知乎上的一个问题 《为什么不能说 20℃ 是 10℃ 的两倍?》:在统计学中,数字其实分四种尺度,而摄氏度属于「定距数据」—— 有顺序、能比大小、差值有意义,但比例没意义,所以只能加减、不能乘除(不过可以算平均值)。