真實世界的 Go 設計模式 - 原型模式

原型模式是創建型模式的一種,其特點在於通過 “複製” 一個已經存在的實例來返回新的實例, 而不是新建實例。被複制的實例就是我們所稱的“原型”,這個原型是可定製的。

如果你有一個對象,  並希望生成與其完全相同或者類似的一個複製品,  你該如何實現呢?  首先,  你必須新建一個屬於相同類的對象,或者類似的對象,  然後你必須遍歷原始對象的所有成員變量,  並將成員變量值複製到新對象中。在 Go 生態圈中,我們常常使用下面的庫來做這份工作:

當然你也可以自己實現轉換的方法,最簡單的方式就是:

var newValue = value
var newValue = *valuePointer

但是這種複製也有一些侷限性,比如在一些字段複製的值要進行調整,新的對象中有些字段不需要設置等等,所以一般我們有預見對象需要複製 (克隆) 的話,我們一般會爲這個對象類型實現Clone方法,通過這種方式我們實現原型模式。

實際上,Go 標準庫有很多實現原型模式的例子。

strings.Clone

func Clone(s string) string

Clone 返回字符串 s 的一個全新副本。它保證將字符串 s 複製到一個新的分配空間中, 當只保留一個大字符串的一小部分子串時, 這可能非常重要。使用 Clone 可以幫助這些程序減少內存使用或者說避免內存泄露。

maps.Clone

func Clone[M ~map[K]V, K comparable, V any](m M "M ~map[K]V, K comparable, V any") M

Clone 返回 m 的一個副本。這是一個淺克隆: 新鍵和值是使用普通賦值設置的。

http.Transport.Clone

func (t *Transport) Clone() *Transport

Clone 返回 t 的導出字段的深度拷貝。

arena.Clone

func Clone[T any](s T "T any") T

Clone 方法返回一個 s 的淺拷貝,此拷貝的對象不再在 arena 中分配。

arena 包還不成熟

slog.Record.Clone

func (r Record) Clone() Record

Clone 返回一個沒有共享狀態的記錄副本。原記錄和克隆記錄都可以修改, 而不會相互影響。

此外,還有 Go 標準庫還有很多類似的實現原型模式的例子,比如:

還有一些非導出的方法和函數。

總的來說,如果你想實現原型模式,那麼最簡單的方式就是爲你的類型實現一個 Clone 方法,或者在你的包下實現一個 clone 函數。

參考資料

[1]

jinzhu/copier: https://github.com/jinzhu/copier

[2]

switchupcb/copygen: https://github.com/switchupcb/copygen

[3]

jmattheis/goverter: https://github.com/jmattheis/goverter

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/R1bPyZBMWizcfuwQv0-t8Q