參考 Streamlit 的 Component Create Function,我們也需要為 Component 的函數提供多種參數選項。雖然 Golang 本身並不直接支持 Overload ,但我們仍有幾種方法來實現類似的功能,其中最常見的兩種是 Option Pattern 和 Config Pattern。
Option Pattern 的核心思想是通過一系列函數來表示不同的參數選項,這些函數通常以 WithXXX 的形式命名。使用時,我們可以將這些函數作為參數傳遞給目標函數。這種方式靈活且可擴展:
func Foo(options ...Option) {
// ...
}
bar.Foo(
bar.WithTimeout(123),
bar.WithLength(789),
)
但就 ToolGUI 目前的架構,export 的 Function / Struct 越多,Duplicate 的部分就越多。
而且目前多個 Component 都在同一個 package,假如每個 component 都要有 Option ,又要避免撞名,可能會變成:
tgcomp.Textbox(...,
tgcomp.TextboxWithXXX(?),
tgcomp.TextboxWithYYY(?))
也就是說,WithXXX 前面還會再多 Component Name。
Config Pattern 則將所有參數選項塞到一個 Struct 中。使用時,我們只需要傳遞這個 Struct 作為參數即可。
tgcomp.Textbox(..., &tgcomp.TextboxConf{
// ...
})
經過比較,我選擇了 Config Pattern。這種方式在 ToolGUI 的現有架構下,可以有效減少重複代碼,並避免命名衝突。
我嘗試將 Config Pattern 應用於之前的一些 Component,並添加了一些新的參數,效果不錯。
type DownloadButtonConf struct {
// MIME specifies the Multipurpose Internet Mail Extension (MIME) type of the downloaded content.
// Defaults to "application/octet-stream" if not provided.
MIME string
// Color defines the color of the download button.
Color tcutil.Color
// Disabled indicates whether the download button should be initially disabled.
Disabled bool
// Filename sets the suggested filename for the downloaded content when clicked.
Filename string
ID string
}
// DownloadButton create a download button component.
func DownloadButton(c *tgframe.Container, text string, body []byte) {
DownloadButtonWithConf(c, text, body, nil)
}
// DownloadButtonWithConf create a download button component with a user specific config.
// If no configuration is provided, a new one with default values is used.
func DownloadButtonWithConf(c *tgframe.Container, text string,
body []byte, conf *DownloadButtonConf) {
// ...
}