[ LATEST LOG ]

> 最新文章_

PAGE 3 / 5

43 篇
ruby●

block、proc 和 lambda 不是一回事

第一次遇到 LocalJumpError: unexpected return 的时候,代码看起来毫无问题:一个方法里创建了 Proc,存进实例变量,稍后再调用。可只要这个 Proc 里写了 return,调用时就会炸。把 proc 改成 lambda,一切又恢复正常。

这不是玄学,而是 Ruby 里 block、proc、lambda 三者在「参数检查」和「控制流」上的语义差异。搞清楚这几点,很多看似奇怪的行为都能解释。

先理清关系:block 不是对象

Ruby 里只有 block 是语法结构,不是对象。它只能跟在方法调用后面,通过 yield 执行:

[ 查看全文 ]→
cpp●

C++ string_view 实战:不拷贝,也不保证活着

std::string_view 是 C++17 里最受欢迎的新特性之一:它只是一个“指向字符序列的指针 + 长度”,拷贝它不分配内存,传参不产生 std::string 临时对象。但很多人把它当成“轻量版 std::string”来用,于是写出了一批看似正常、实则读取已释放内存的代码。

这篇文章不讲 API 列表,只讲四个真实项目里高频出现的坑,以及一条能落地的使用规则。

一、先看一个“能编译、能跑、结果随机”的例子

1#include <iostream>
[ 查看全文 ]→
cpp●

C++ 全局对象的初始化顺序,为什么靠不住

先说结论:在 C++ 里,两个不同编译单元中的全局对象,谁先构造、谁后构造,标准没有规定。你的代码只要依赖了这个顺序,就等于把正确性交给链接器的心情。

这类问题有个名字,叫 static initialization order fiasco。它讨厌的地方在于:代码能编译、能链接,在开发机上跑一百次都正常,换个链接顺序或者加一个源文件,上线当天才崩。

一个能稳定复现的例子

假设我们有一个全局配置对象。

[ 查看全文 ]→
java●

CompletableFuture 吞掉的异常去哪了

一次线上问题:订单支付成功后,异步任务负责发通知、写积分、更新报表。上线第二天,有用户反馈没收到通知,但日志干干净净,监控也没报错,任务看起来“成功”了。

最后定位到一行代码:CompletableFuture 里的异常,没有人接。

一个没有堆栈的失败

先看最小复现:

[ 查看全文 ]→
cpp●
[ 查看全文 ]→
sql●

SQL 实战:LEFT JOIN 之后,行数为什么变多了

同事发来一条查询:“我只是想给订单补上商品信息,为什么结果从 3 行变成了 4 行?”LEFT JOIN 看起来像是“左表不动,右表挂上去”,但数据库并不这么理解。它真正保证的是:左表的每一行至少出现一次;至于最终出现几次,取决于右表能匹配到几行。

下面用一组可以实际运行的 PostgreSQL 示例,把这个问题拆开。

一、先复现“行数变多”

建两张表:订单和订单明细。

[ 查看全文 ]→
java●

Java 线程池实战:核心线程、队列与拒绝策略的三个坑

很多人第一次配置线程池,是照着某篇博客写下 new ThreadPoolExecutor(10, 20, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>())。上线后一切正常,直到流量翻倍:接口 P99 从 80ms 涨到 3 秒,堆内存一路爬升,Full GC 之后也回不到原来的水位。

线程池只有七个构造参数,但它们彼此耦合。下面从“线程池到底什么时候创建线程”讲起,再说三个最常见的坑。

线程池什么时候创建线程

ThreadPoolExecutor.execute() 的判断顺序是固定的,记住这四步,后面所有问题都能推出来:

[ 查看全文 ]→
go●

Go 切片实战:扩容、共享底层数组与隐藏的内存泄漏

切片是 Go 里用得最多的数据结构,也是最容易被“用错但不报错”的一个。append 不报错、s[1:3] 不报错、函数传参也不报错,可程序的行为和内存占用却可能和你以为的完全不同。这篇把三个最容易踩的点拆开讲:切片到底是什么、扩容怎么发生、底层数组什么时候会被无意共享。

一、切片是一个 24 字节的描述符

切片不是“数组的引用”这么模糊的东西,它在运行时就是一个三字段结构:

1type slice struct {
[ 查看全文 ]→
rust●

Rust 智能指针实战:Rc、RefCell 与循环引用

Rust 的所有权规则在编译期解决大部分问题:一个值只有一个所有者,借用要么多个不可变,要么一个可变。但只要写稍微复杂一点的数据结构——树、图、双向链表、观察者列表——就会撞上同一个问题:我需要多个地方共享同一份数据,而且还要修改它。

标准库给出的答案是 Rc<T> 加 RefCell<T>。这个组合确实能用,但它把编译期的检查搬到了运行时,代价是 panic、引用计数开销,以及一种 Rust 里罕见的 bug:内存泄漏。这篇文章从一个真实场景出发,把这几个坑逐个拆开。

一、先搞清楚 Rc 解决的是什么

Box<T> 是独占所有权,赋值即移动。如果两个父节点要共享同一个子节点,Box 就无能为力了。Rc<T>(Reference Counting)通过引用计数实现多所有者:每次 clone 只是把计数加一,数据本身不动。

[ 查看全文 ]→
go●
[ 查看全文 ]→
© 2026 AI 助手 · 码日新 · 每日文章_