王昊 ☕️
王昊 Wang Hao

Research and Development

About Me

I completed(may be) my undergraduate and master’s degrees at China University of Geosciences, Wuhan, and I am interested in mathematics and algorithms.

Interests
  • Graph Theory and Combinatorics
  • Data structure and Algorithms
  • Artificial Intelligence
Education
  • Artificial Intelligence

    China University of Geosciences, Wuhan

  • Artificial Intelligence

    China University of Geosciences, Wuhan

Recent Publications
Recent News

From unique to cleanups and weak new low-level tools for efficiency

📌 背景与动机

在过去,Go 语言提供了 runtime.SetFinalizer 方法来处理对象被垃圾回收时的清理操作(Finalizer)。
但 Finalizer 存在一些固有问题:

  • 如果对象之间有循环引用,Finalizer 可能永远不会被调用,导致内存泄漏。
  • Finalizer 会延迟对象的回收,至少需要两个垃圾回收周期才能彻底清除对象。
  • Finalizer 有可能让对象“复活”(Resurrection),导致原本应被释放的对象意外存活下来,造成内存浪费。

因此,Go 在 1.24 版本推出了两个新功能:

  • runtime.AddCleanup:更安全的对象清理方法。
  • weak.Pointer:弱引用指针类型,可以引用对象但不会阻止对象被回收。

这两个功能结合使用,能有效解决传统 Finalizer 的问题,并构建更高效、更安全的数据结构,比如缓存或去重机制。


📌 一、runtime.AddCleanup(安全清理函数)

runtime.AddCleanup 允许给一个对象附加一个“清理函数”,当该对象变得不可达(即垃圾回收后)时,清理函数将被执行。

示例:使用内存映射文件(memory-mapped file)

Goodbye core types-Hello Go as we know and love it!

📌 一、理解背景:Go语言泛型(Generics)的引入

在 Go 1.18(2022年3月发布)以前,Go语言并没有泛型功能(generics)。所谓泛型就是写函数或数据结构时,可以不指定具体类型,而用类型参数代替,然后调用时再填入具体类型,这样函数可以用于很多不同类型的情况。

比如:

// 没有泛型之前,得为每种类型写一个函数
func SumInt(a, b int) int { return a + b }
func SumFloat(a, b float64) float64 { return a + b }

// 泛型后,可以只写一个函数:
func Sum[T int | float64](a, b T) T { return a + b }

泛型的引入使Go语言更灵活、更强大。但随之而来,语言内部实现变得复杂了。


📌 二、理解类型参数、类型约束和类型集

泛型中出现了一些重要概念:

  • 类型参数(Type Parameter)

    就是泛型函数或泛型结构体中用来代替具体类型的占位符,类似函数参数。

    func Example[T any](value T) T {
        return value
    }
    

    这里T就是一个类型参数。

  • 类型约束(Type Constraint)

    表示一个类型参数能取哪些具体类型的限制。用接口表示:

    type MyConstraint interface {
        ~string | ~[]byte
        Hash() uint64
    }
    

    这个约束表示任何底层类型是string[]byte,并且实现了Hash()方法的类型都可以满足。

Testing concurrent code with testing/synctest

使用testing/synctest测试并发代码

Go 的一个标志性特性是对并发的内建支持。Goroutine 和 channel 是用于编写并发程序的简单而有效的原语。

然而,测试并发程序可能是困难且容易出错的。

在 Go 1.24 中,我们引入了一个新的实验性包 testing/synctest,用于支持并发代码的测试。本文将解释该实验背后的动机,演示如何使用 synctest 包,并讨论其未来的潜力。

💡 testing/synctest 是实验性的,不受 Go 兼容性承诺的约束。
默认情况下不可见。要使用它,请在环境中设置:
GOEXPERIMENT=synctest


并发程序的测试很难

让我们从一个简单的例子开始。

context.AfterFunc 函数会安排在 context 被取消后调用一个函数,该函数会在自己的 goroutine 中执行。下面是一个可能用于测试 AfterFunc 的例子:

Traversal-resistant file APIs

📌 一、路径遍历攻击是什么?

路径遍历(Path Traversal)攻击是一种安全漏洞,攻击者通过控制程序访问文件的路径,使程序打开了原本未授权访问的敏感文件。


📌 二、典型漏洞示例(易受攻击的代码)

存在漏洞的代码通常长这样:

// baseDirectory 是受信任的固定目录
// filename 是用户可控制的输入
f, err := os.Open(filepath.Join(baseDirectory, filename))

为什么这段代码有漏洞?

假设:

baseDirectory := "/var/www/data"
filename := "../../../../etc/passwd"

执行后:

filepath.Join("/var/www/data", "../../../../etc/passwd")
// 实际路径:"/etc/passwd"

攻击者成功跳出了本来限定的目录(/var/www/data),访问到了敏感文件。


📌 三、为什么传统路径检查不够安全?

你可能会想自己手动验证,比如:

// 手动检查路径安全性(不推荐)
if strings.Contains(filename, "..") {
    return errors.New("路径不安全")
}
f, err := os.Open(filepath.Join(baseDirectory, filename))

但这种检查方式不安全,原因如下:

fuck the life!

随笔

最近有点迷茫,要学的东西很多,但是没有动力学习