Go1.25 新特性:新增 slog.GroupAttrs 和 hash.Clone,實屬是技巧優(yōu)化
大家好,我是煎魚。
之前已經(jīng)給大家介紹過多輪 Go1.25 新特性,在今天這篇文章中,我們繼續(xù)給大家分享兩個編碼上的新特性。
希望能夠給大家?guī)硪稽c小的優(yōu)化幫助。
log/slog 新增 GroupAttrs 方法
背景
社區(qū)小伙伴 @Sean Liao 在實際使用時,發(fā)現(xiàn)雖然當(dāng)前 log/slog 中的記錄結(jié)構(gòu)(Record)擁有多個屬性,但沒有內(nèi)建便捷的方式將它們歸整成 Group。比較麻煩。
現(xiàn)在 slog 通過 Group 來組裝的寫法:
attrs := []slog.Attr{
slog.String("first", "a"),
slog.String("second", "b"),
}
logger.LogAttrs(ctx, slog.LevelInfo, "msg", slog.Group("group", attrs...))會有些不夠簡潔。
新提案
為此提出了新的提案《log/slog: GroupAttrs(key, attrs....Attr)[1]》:
圖片
該提案旨在為 log/slog 包引入一個新的輔助函數(shù) GroupAttrs。
以便更便捷地構(gòu)造分組屬性(attributes),也就是將一系列屬性封裝為一個分組(groups)屬性。
例子
本次 Go1.25 新引入的 GroupAttrs 函數(shù)簽名如下:
// GroupAttrs returns an [Attr] for a Group [Value] consisting of the given [Attr]s.
//
// GroupAttrs is a more efficient version of [Group] that accepts only [Attr]s.
func GroupAttrs(key, attrs....Attr) Attr提案后的新寫法:
attrs := []slog.Attr{
slog.String("first", "a"),
slog.String("second", "b"),
}
logger.LogAttrs(ctx, slog.LevelInfo, "msg", slog.GroupAttrs("group", attrs))將會更直接,更便利。
引入緣由和進(jìn)展
該提案解決了 log/slog 在 Groups 屬性構(gòu)造時的易用性問題,尤其是在動態(tài)屬性場景下,能減少樣板代碼,讓結(jié)構(gòu)化日志更易書寫與維護(hù)。
目前該提案已經(jīng)被 Accepted 并加入 Go1.25 新版本的 API 變動說明中:
圖片
如果有使用 slog 標(biāo)準(zhǔn)庫的同學(xué)可以跟進(jìn)。
hash 新增 Clone 方法
背景
社區(qū)小伙伴 @Filippo Valsorda 發(fā)現(xiàn)一些底層加密庫(如 Windows 的 CNG 或 OpenSSL)本身是支持 clone 操作的。
但 Go 標(biāo)準(zhǔn)庫缺少統(tǒng)一的接口來對接這些能力,另外通過序列化再反序列化來克隆狀態(tài)也不夠方便或高效。
新提案
因此提出新提案《hash: add Clone[2]》:
圖片
為 Go 的 hash 包增加一個 Cloner 接口,用于優(yōu)雅地克隆哈希實例(包含當(dāng)前的內(nèi)部狀態(tài))。
以解決現(xiàn)有 API 中序列化狀態(tài)的方法(如使用 MarshalBinary / UnmarshalBinary)不夠清晰或靈活的問題。
例子
本次新增的 Cloner 接口的聲明如下:
// https://github.com/golang/go/blob/master/src/hash/hash.go
type Cloner interface {
Hash
Clone() (Cloner, error)
}
type Hash interface {
// Write (via the embedded io.Writer interface) adds more data to the running hash.
// It never returns an error.
io.Writer
// Sum appends the current hash to b and returns the resulting slice.
// It does not change the underlying hash state.
Sum(b []byte) []byte
// Reset resets the Hash to its initial state.
Reset()
// Size returns the number of bytes Sum will return.
Size() int
// BlockSize returns the hash's underlying block size.
// The Write method must be able to accept any amount
// of data, but it may operate more efficiently if all writes
// are a multiple of the block size.
BlockSize() int
}由于提案中沒有提供例子,我們可以大致構(gòu)建了解:
h := sha256.New() // 假設(shè)它實現(xiàn)了 Cloner
h.Write([]byte("prefix"))
h0 := h.(hash.Cloner).Clone()
for _, msg := range messages {
h1 := h0.Clone()
h1.Write([]byte(msg))
fmt.Printf("%x\n", h1.Sum(nil))
}這樣可以借助 Clone() 在重復(fù)使用前綴(prefix)、避免多次 Write(prefix) 的場景下的優(yōu)勢。
大概會是如此使用的場景。
引入緣由和進(jìn)展
這個提案新增了 Clone() 后可以明確表達(dá)克隆當(dāng)前哈希狀態(tài)的意圖統(tǒng)一接口便于不同的 hash 實現(xiàn)。簡化了不少繁雜的實現(xiàn)。
該提案目前已經(jīng) Accepted 并被放入 Go1.25 新特性中,相信很快就可以和大家見面啦。
圖片
總結(jié)
本次給大家介紹的 Go1.25 新特性 log/slog 庫新增 GroupAttrs 方法和 hash 庫新增 Clone 方法,主要是針對日常使用中的一些小場景優(yōu)化。
也算是一點點編碼技巧上的提效了。
參考資料
[1] log/slog: GroupAttrs(key, attrs....Attr): https://github.com/golang/go/issues/66365
[2] hash: add Clone: https://github.com/golang/go/issues/69521


































