我是卡斯,欢迎光临我的博客。
Weekly #004 - OpenClaw 降临,而我在留恋旧时代
前言 本篇是对 2026-01-26 到 2026-02-01 这周生活的记录与思考。 本周最大的热点莫过于 OpenClaw·Moltbot·Clawdbot 的火爆出圈。从国内到国外,社交媒体全被这几个关键词占领,让人避无可避。 我向来不是喜欢凑热闹的人,等这阵热潮过去之后,我再考虑要不要部署一个试试。 LeetCode 突然开始做 LeetCode 的原因是参与 yihong0618 在他的频道发布的每日一题😄 现在是 AI 纪元了,做不出来也不必自己死磕,发给 Gemini 让它给我提示思路,然后尝试自己实现,完了再把代码发给它检查。 顺便吐槽一下,写 Rust 心智负担真的好大啊,我每次都是先写 Go,过了再翻译成 Rust…… 2085. 统计出现过一次的公共字符串 Rust 一血 53. 最大子数组和 733. 图像渲染 运动 本周跑步 2 次,累计 12.6 公里 本月累计跑步 5.0 公里 本年累计跑步 33.9 公里 周日看了别府大分马拉松的直播,见证了最后 10 公里吉田祐也和黑田朝日的极限对决,真是太精彩了!我很期待黑田小队长在未来的几年时间里对大破杰的日本马拉松纪录发起冲击。 本周发现 影视 《NANA》(2006) 一部我在2011年标记想看的片子,显然15年后的我已不是剧中的年纪,但剧中人错综复杂的微妙情感确实让我印象深刻。 《爱乐之城》(2016) 不论是剧情还是美术都很喜欢。美术有一种油画的质感,我尤其喜欢夜间的灯光打在人物身上的效果,简直绝了。 《青蛇》(1993) 不合我的胃口。 《东邪西毒》 (1994) 影片的节奏很王家卫。看完的感受就是:爱要大声说出口。 最近补的好几部老电影里都有张曼玉,她真的太有魅力了。 收藏 Go kit A toolkit for microservices
Weekly #003 - 你听说过 Rust 吗
前言 本篇是对 2026-01-19 到 2026-01-25 这周生活的记录与思考。 浅尝 Rust 我畏惧于传说中 Rust 陡峭的学习曲线,一直没敢下手。这周无意中看到了《Rust语言圣经》 这本在线开源书籍,那就择日不如撞日,索性尝试学一下。这本书真的挺不错的,还有配套的习题,甚至习题支持在线编译。我稍微了解了一下 Rust 在内存管理方面的尝试,感觉挺有意思的。不同于 C++ 的手动管理和 Go 的 GC,Rust 通过所有权来管理内存,简单来说就是一个值同时只能被一个变量所拥有,当所有者(变量)离开作用域范围时,这个值将被丢弃。因为这条规则的存在,让我在学习的时候感觉到需要用一种全新的思维模式去写程序,这是我以前学习新语言的时候从未有过的体验。 目前这本书我只学了一半,也只刚学完了一些基本知识,还没学到 Rust 中令人闻风丧胆的生命周期,希望我能坚持下去吧。我也没有想到学了 Rust 之后用来作什么用,总之先学了再说吧。 运动 本周跑步 1 次,累计 9.1 公里 本月累计跑步 21.3 公里 本年累计跑步 21.3 公里 本周发现 书籍 《Rust语言圣经》 影视 《重返·狼群》 虽然影片有些地方看着刻意,也有主人公过度解读和自我感动的部分,但人与狼的羁绊是真实存在的。 播客 面基 | E134.跑外卖:在加速的时间里,在算法和现实夹缝中逆行 文化有限 | Vol.314 冬日特辑:没有坏天气,只有不同种类的阳光和雪 收藏 文颜 Markdown 转微信公众号排版助手,有 Win/Mac/CLI 客户端,甚至有个 MCP 版 日本語自習資料 goforj/godump 可读性更好的 Go 数据结构打印工具 Wolfcha(猹杀) 除了你自己,其他所有角色都由 AI 扮演的狼人杀。太好了,解决了本社恐玩狼人杀最大的心理障碍。 文章 生来取代Docker、JS,谷歌力推,这项技术发布7年后,现状如何? 经常看到 WebAssembly 这个词,却从没有了解过具体是什么技术,这篇文章算是很好的科普了。 Golang后台服务性能优化,实用Tips梳理大全 Go GC 原理及性能优化。 大牛书单 | Rust 好书推荐 鹅厂程序员推荐的 Rust 书单。 Thoughts on Go vs. Rust vs. Zig 简单比较了这三种语言,恰好我对这三种语言都有兴趣。此刻,我在靠 Go 混饭,正开始学 Rust,以后可能会学 Zig。
Weekly #002 - 重启试试 ?
前言 本篇是对 2026-01-12 到 2026-01-18 这周生活的记录与思考。 重启周报 不容易啊,距离上一份周报已经半年多了。我发现周末很难抽出较长的时间打开电脑坐下来慢慢写一份周报。现在我在 Gemini 的建议下正尝试一种新的方式来写周报。简单来说就是每周在 Github 的博客仓库里新开一个 issue,然后不定时地记录内容,到周日晚上, GitHub Action 自动读取这个 issue 的内容生成周报,然后自动提交 PR,最后我检查内容没问题就可以发布了。 运动 本周跑步 1 次,累计 6.8 公里 本周徒步 1 次 本月累计跑步 12.2 公里 本年累计跑步 12.2 公里 没错,上面的数据也是 GitHub Action 通过 Strava API 自动统计的。 周日去西湖群山徒步了,还挺开心的😆 本周发现 书籍 《欢乐英雄》 似乎是古龙在豆瓣评分最高的作品。非传统意义上的武侠小说,有点无厘头,有点欢笑,有点装逼。看的时候不要太较真,开心就好。 影视 《无耻混蛋》 《虎口脱险》之后的另一部豆瓣Top250里的二战片,说实话同样不太合我的胃口,可能是文化背景不同。 《人之初》 下饭看的,剧本不行,年轻演员的演技也相当尴尬,不推荐。 收藏 VidBee 视频下载器 Tadoku 免费日语入门读物 适合像我一样刚学完日语五十音的初学者
Weekly #001 - 开始写点东西
前言 本篇是对 2025-06-23 到 2025-06-29 这周生活的记录与思考。 这篇周报我参考了 pseudoyu 的周报形式,我希望可以跟他一样用文字记录自己的生活。 微信公众号 我有一个建立了超过 10 年的个人博客,但博文不过寥寥十多篇,而且停更已久。我也早在 2018 年就注册了公众号,但未曾发出一篇文章。现在我想重新捡起这个号,争取每周都能写点什么,同步发在博客和公众号上。不出意外的话,这篇会是这个号的第一篇文章。 我曾幻想自己成为一个有旺盛表达欲的人,但事实并非如此,我的表达欲通常在打开编辑框的时候就已经所剩无几。我觉得想要改变别无他法,只能强迫自己多写一点。 运动 本周我尝试了 3 次爬楼梯运动。出乎意料,在边爬边听播客的情况下,这项运动并没有我想象中的那么无聊。我过去的锻炼都是以跑步为主,但是最近重新开始上班之后,工作和通勤使我不能很好地挤出时间来坚持跑步,而且夏天跑步高温和防晒是大难题。经过这周的尝试,我发现爬楼非常经济,走出家门可以马上开始,中途如果有需要的话甚至可以回家补水。除此之外,对我来说爬楼还有个优势,就是可以比较容易得把心率保持在有氧区间,能达到比较好的锻炼效果。 在接近中断了一个月的跑步之后,爬楼似乎让我找回了运动的快乐,让我重新找回了一点对身体的掌控感。 小游戏开发 从上周开始,我尝试学习从头开发一款微信小游戏。客户端框架我选择的是 Cocos Creator 当前最新的 3.8.6 版本。服务端框架选择几经波折。我在看了《TSRPC + Cocos,多人实时对战 So Easy!》 这篇文章之后非常惊喜,对 TSRPC 跃跃欲试。我在 TSRPC 的文档里看到这个框架支持云函数部署,我觉得微信小游戏的服务端用云函数实现可以节省成本。但是经过我的简单尝试之后,我发现事情并不乐观。首先 TSRPC 的文档有点旧了,云函数部署的 example 不论在阿里云还是腾讯云并没有立即成功。其次腾讯云上云函数支持的 Node.js 版本只到 v18.15,拜托现在 Node.js 最新的 LTS 版本都到 v22.17 了好吧,这让我对云函数这个产品的发展非常没有信心。既然不选择云函数部署的话,那服务端的语言我便选择了自己最熟悉的 Go,部署大概率会选择微信云托管的方式。因为是休闲游戏,所以我选择了短连接的方式实现通信。 目前小游戏完成了客户端玩法的大概流程,服务端完成了登陆接口,还没有实现前后端的对接。 Go Web 后端框架选型 上面提到小游戏服务端语言我选择了 Go,框架我最终选择的是 go-nunu/nunu。严格来说 nunu 不是一个框架,是一个 Go 应用脚手架,通过它可以快速搭建一个 Go 的应用的项目结构。我在前司曾经使用过一年多的 go-zero 框架,但是不知道为什么,始终对这个框架没什么兴趣。另外我对 B 站开源的 kratos 框架非常感兴趣,曾经多次尝试用这个框架搭建 Web 后端程序,但是最终都失败了。我感觉 kratos 给我造成了挺重的理解负担,在我看来比较适合搭建大型的微服务应用,在个人项目搭建简单的单体 Web 后端方面,显得非常冗余,写起来不够灵活。最终我选择了更简单的 nunu,它只是一个简单脚手架工具,适合快速搭建一个简单的 Web 后端工程,并且自带分层架构和单元测试的设计。nunu 从各方面来说都非常灵活,用起来感觉很自由轻量,符合 Go 这个语言本身的感觉,相比之下 kratos 总给我一种笨重感。 ...
Ubuntu 20.04 设置窗口打不开或不显示解决方法
我最近又心血来潮,翻出家里的旧笔记本,装上了 Ubuntu 20.04 LTS Desktop 版本,打算用来偶尔写写代码用。至于为什么选Ubuntu 是因为我觉得选择个最不折腾。事实证明我错了,我不应该信任任何 Linux Desktop 发行版。我刚装完系统,然后一通 apt update 和 apt upgrade,再 reboot 一下。然后我就发现一个蛋疼的问题,设置窗口打不开了,确切的说是不显示了。然后就 Google 一通搜,发现碰到这问题的人还真不少,从 Ubuntu 17 时代就有人碰到了。解决方法说啥的都有:什么 reinstall gnome-control-center,甚至有让人重装系统解决问题的,简直离谱。功夫不负有心人,我总算找到了正确的解决方法,现在记录下来,希望下一个碰到这个问题的可怜孩子能看到这篇文章。 症状 打开设置的时候,能看到侧边栏上有设置图标,但是屏幕上看不到设置窗口。在设置图标上右键点「所有窗口」,能看到设置窗口的预览。初步猜测,设置是正常打开的,但是窗口显示到屏幕外面出去了,导致我们看不到。 解决方法 左手按住Ctrl+F7,然后右手把鼠标向左拖动,记住这个时候不需要按鼠标上的任何键,然后你就会看到奇迹发生了:设置窗口被从屏幕右边拖出来了! 看来问题真的是窗口显示到屏幕的外面去了,我们现在把它拖回来了。但是问题并没有真正解决,当你下次再打开设置的时候,窗口依然显示在屏幕外面。 打开设置里面的「显示器」选项,你会看到,不知道在什么时候,「显示模式」这个选项被设置成了「加入显示器(Join Displays)」,现在把它改成「单显示器(Single Display)」。然后一切就正常了。 参考 https://askubuntu.com/a/1111186
Docker Hub 根据 GitHub Tags 自动构建带版本号镜像
自从去年买了一个蜗牛矿渣当作 NAS 开始,我就在折腾 NAS 这条路上越走越远。在 NAS上折腾软件和服务最方便的就是通过 docker 部署。所以能找到 docker 镜像的软件,我绝对不会自己折腾安装过程。当然有些时候没有办法找到现成的 docker 镜像,那就自己动手构建镜像。 众所周知,我们可以通过 Docker Hub 的自动化构建存放在 GitHub 上某个 branch 的代码。每当我们 git push 代码到 GitHub 就会触发一次 Docker Hub 构建一个新版本。 但是我最近发现一个问题,就是每次构建出来的镜像都是 latest 版本,没有留下历史版本的镜像,这就很不方便。比如我新构建的镜像有问题,但是没办法立刻回退到上一个版本的镜像,除非我把代码改回去再构建一次,这事儿听起来就很不科学。 当然 Docker Hub 也可以根据 GitHub 的特定 Tag 来自动构建镜像。难道我每次在 GitHub 创建一个新的 Tag 都要在 Docker Hub 上创建一条新的构建规则吗?这事儿听起来也挺蠢的。 有没有办法当我在 GitHub 创建一个任意版本号的 Tag 的时候,Docker Hub 这边都自动根据这个 Tag 的版本号,自动构建一个对应版本号的镜像呢?答案当然是有的,Docker Hub 的自动构建规则支持表达式匹配 Tag。 我们可以新增一条如下的自动构建规则: Source Type Source Docker Tag Tag /^v([0-9]+).([0-9]+).([0-9]+)$/ {\1}.{\2}.{\3} 然后当我们在 GitHub 创建一个 v0.1.1 的 Tag 之后, Docker Hub 会自动构建一个版本号为 0.1.1 的镜像。 ...
碎片 Collection 第1期
分享每周收集的碎片化知识和资讯。 技术 Ubuntu 18.04 设置静态 IP 的方法 在 Ubuntu 17.10 包括之前版本中可以通过修改 /etc/network/interfaces 设置静态 IP。但是在18.04 之后 Ubuntu 采用了新的 Netplan 程序管理网络配置,那么设置静态 IP 的方法就有些不同了。 sudo vim /etc/netplan/50-cloud-init.yaml network: ethernets: enp0s3: #dhep4: true dhcp4: false addresses:[192.168.2.90/24] gateway4: 192.168.2.1 nameservers: addresses:[8.8.8.8, 1.1.1.1] version: 2 sudo netplan apply 参考:Setting up your static IP address since Ubuntu 18.04 命令行代理设置 export ALL_PROXY=socks5://127.0.0.1:1080 export ALL_PROXY=http://127.0.0.1:8118 unset ALL_PROXY nginx warn:a client request body is buffered to a temporary file ...
LeetCode 029 — Divide Two Integers
Divide Two Integers https://leetcode.com/problems/divide-two-integers/ 题目要求不用乘法、除法和取模运算符,实现整型除法运算。 既然不能用乘法和除法运算符,那么基本思路就是用减法来代替。不过如果用每次循环减一次被除数这种方式,是肯定会超时的。所以要想办法加速运算。 Solution class Solution { public: int divide(int dividend, int divisor) { long long quotient = 0; int flag = 1; auto dividend1 = (long long)fabs(dividend); auto divisor1 = (long long)fabs(divisor); if(dividend < 0) { flag = -1; } if(divisor < 0) { flag = flag == 1 ? -1 : 1; } std::vector<std::pair<long long, long long> > vec; long long times = 1; while (dividend1 >= divisor1) { vec.emplace_back(divisor1, times); dividend1 -= divisor1; quotient += times; divisor1 += divisor1; times += times; } for (int i = vec.size() - 1; i >= 0; --i) { while(dividend1 >= vec[i].first) { quotient += vec[i].second; dividend1 -= vec[i].first; } } if(flag == -1) { quotient = -quotient; } if(quotient > INT32_MAX) { return INT32_MAX; } else if (quotient < INT32_MIN) { return INT32_MIN; } return quotient; } }; 首先,我们用两个 long long 的 dividend1, divisor1 来把传进来的参数转成绝对值,用 flag 记下符号,去掉负号方便后面的运算。 ...
LeetCode 011 — Container With Most Water
Container With Most Water https://leetcode.com/problems/container-with-most-water/ 给定一个整型数组,表示坐标轴上的一组相应长度的垂直于 x 轴的线段,要求找出两条线跟 x 轴围起来的容器,能装最多的水。 这题一开始我想用最暴力的方法做两层循环O(n^2)的解法提交试一下,可惜超时了,果然 Medium 难度的题目不会这么轻松放我过去的。 既然 O(n^2) 的解法没有办法通过,那就要想办法能不能找出 O(n) 的解法,一遍循环弄出来。我绞尽脑汁想了很久,尝试了好几种方案,始终没有办法解决。我最终不得不求助于前人的经验,看到别人的解法之后,顿时觉得豁然开朗。 Solution class Solution { public: int maxArea(vector<int>& height) { int max_area = 0; int area = 0; int i = 0; int j = height.size() - 1; while(i < j) { if(height[i] > height[j]) { area = (j - i) * height[j]; --j; } else { area = (j - i) * height[i]; ++i; } if(area > max_area) { max_area = area; } } return max_area; } }; 其实这个解法的关键是用两个指针,分别从左右两边向中间开始遍历,每次算出当前两个指针所指的线围成的面积,并比较是不是当前最大的记到 max_area 里,然后每次排除较短的一条线段,继续遍历。 ...
ARTS 打卡 第一周
ARTS 是由陈皓(网名「左耳朵耗子」)在极客时间上发起的一个每周打卡计划,详情查看 https://www.zhihu.com/question/301150832 。 Algorithm LeetCode 009 — Palindrome Number Review How to think like a programmer — lessons in problem solving 这是 Medium 上的一篇文章,名字翻译成中文是《怎样像程序员一样思考》。 文章的开头说「像程序员一样思考」实际上是指一种更有效的解决问题的方法。 我们每个人总是碰到各种各样的问题,或大或小。我们处理这些问题的方式,从某种程度上来说,非常随机。一般人们总是这样来解决一个问题:首先尝试一种解决方法;如果这种方式不起作用,那么就尝试另外一种;如果依然不起作用,那么重复第二个步骤,直到你足够幸运解决了问题。有的时候,你足够幸运,但是这是解决问题最差的方式。 解决一个问题最好的方式包括两项:a) 找到一个处理问题的通用框架 b) 不断训练 通用框架 1. 理解问题 理解问题的本质。大多数困难的问题之所以困难是因为你没有理解问题的本质。 2. 做计划 不要在没有做好解决方案的计划之前一头扎进去。要写下解决问题的具体步骤。 3. 分解问题 这是最重要的一个步骤。 不要尝试解决一个巨大的问题,要把它分解成几个子问题。然后依次解决们每一个子问题。最后把这些子问题串联起来,你将会得到原始问题的解决方案。 4. 卡住了? 当你被卡住了,甚至解决不了一个子问题的时候,首先深呼吸,然后你要知道,这是很正常的。 下面是几个你可以尝试的方法: 调试:一步步审视你的解决方案找出你错在哪里。 重新评估问题:从另一个角度观察问题,看看是不是有某些东西能抽象成更通用的途径。 搜索:从搜索引擎寻找解决问题的方式。不管你的问题是什么,很可能别人已经解决过了。 5. 训练 不要期望自己在仅仅一周之后就变得很厉害。如果你希望成为一个很厉害的解决问题的人,那么唯一的途径就是解决很多问题。 不断训练。 Tip ES6 中遍历数组键值对的方法: ES6 提供三个新的方法——entries(),keys()和values()——用于遍历数组。它们都返回一个遍历器对象,可以用for…of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。 for (let index of ['a', 'b'].keys()) { console.log(index); } // 0 // 1 for (let elem of ['a', 'b'].values()) { console.log(elem); } // 'a' // 'b' for (let [index, elem] of ['a', 'b'].entries()) { console.log(index, elem); } // 0 "a" // 1 "b" http://es6.ruanyifeng.com/#docs/array ...