Golang實現函數默認參數

golang原生不支持默認參數

在日常開發中,我們有時候需要使用默認設置,但有時候需要提供自定義設置 結構體/類,在Java我們可以使用無參、有參構造函數來實現,在PHP中我們也可以實現(如 public function xxx($isCName = false, $securityToken = NULL, $requestProxy = NULL))。但在golang中無法這樣做,不過我們可以使用另外一種方式優雅的實現。

golang如何模擬實現默認參數?

在 Go 語言中,函數參數默認值的概念與某些其他編程語言(如 Python)略有不同。Go 語言本身不支持在函數定義中直接為參數設置默認值,這與 Python 或 Java 等語言不同。不過,你可以通過幾種方式模擬出類似的功能:

  1. 使用函數重載
    雖然 Go 不支持傳統意義上的重載(即多個函數名相同但參數不同的定義),但你可以通過不同的函數名來實現類似的效果。

package main

import “fmt”

// 定義兩個函數,一個帶默認參數,一個不帶
func printMessage(message string) {
fmt.Println(“Default message:”, message)
}

func printMessageWithDefault(message string, defaultMessage …string) {
if message == “” && len(defaultMessage) > 0 {
message = defaultMessage[0]
}
fmt.Println(“Custom message:”, message)
}

func main() {
printMessage(“Hello, World!”) // 使用不帶默認參數的函數
printMessageWithDefault(“”) // 使用帶默認參數的函數,傳入空字符串觸發默認值
printMessageWithDefault(“”, “Default”) // 明確指定默認值
}
2. 使用可變參數和切片
如果你想要一個函數可以有或沒有參數,可以考慮使用可變參數或切片。

package main

import “fmt”

func printMessages(messages …string) {
if len(messages) == 0 {
fmt.Println(“No messages provided”)
} else {
for _, msg := range messages {
fmt.Println(msg)
}
}
}

func main() {
printMessages(“Hello”, “World”) // 傳入多個消息
printMessages() // 不傳入任何消息,顯示默認行為
}
3. 使用結構體和指針傳遞默認值
對于更復雜的情況,可以使用結構體和指針來傳遞默認值。

package main

import “fmt”

type Config struct {
Message string
}

func printMessage(config *Config) {
if config == nil {
fmt.Println(“Using default message”)
config = &Config{Message: “Default message”} // 設置默認值并傳遞指針引用
}
fmt.Println(config.Message)
}

func main() {
printMessage(nil) // 使用默認值,因為沒有傳遞非nil的Config實例
config := Config{Message: “Custom message”}
printMessage(&config) // 使用自定義消息
}
4. 使用工廠函數或構造函數模式
創建一個工廠函數或構造函數來返回一個已經配置好的實例。

package main

import “fmt”

type MessagePrinter struct {
message string
}

func NewMessagePrinter(message string) *MessagePrinter {
if message == “” { // 檢查是否需要默認值
message = “Default message” // 設置默認值
}
return &MessagePrinter{message: message} // 返回實例指針,包含配置好的消息值
}

func (mp *MessagePrinter) Print() {
fmt.Println(mp.message) // 打印消息內容
}

func main() {
mp1 := NewMessagePrinter(“”) // 使用默認值創建實例
mp1.Print() // 打印默認消息
mp2 := NewMessagePrinter(“Custom message”) // 使用自定義消息創建實例并

1.舉例
在這之前,我們在golang中大多是使用以下方式來實現的:

type ExampleClient struct {Name stringJob int
}func NewExampleClient(name, job string) ExampleClient {if name == "" {name = "default"}if job == "" {job = "default"}return ExampleClient{Name: name,Job:  job,}
}

這種方式侵入性比較強,如果此時我們需要增加一個超時參數或其他更多參數,那么需要在原代碼基礎上做很多的修改。

2.實現默認參數
在使用go-micro的過程中,發現其初始化服務配置的方式如下👇

func main() {sr := micro.NewService()//或sr := micro.NewService(micro.Name("xxx.xxx.xxx"),micro.Address("192.168.1.1"),)
}

進入到micro.NewService中,可以看到在初始化的過程中都是以type Option func(*Options)類型的函數作為參數,并調用newOptions方法👇

type Option func(*Options)// NewService creates and returns a new Service based on the packages within.
func NewService(opts ...Option) Service {return newService(opts...)
}func newService(opts ...Option) Service {options := newOptions(opts...)// service nameserviceName := options.Server.Options().Name// wrap client to inject From-Service header on any callsoptions.Client = wrapper.FromService(serviceName, options.Client)return &service{opts: options,}
}

我們再接著進入到micro.newOptions中查看👇

type Options struct {Broker    broker.BrokerRegistry  registry.Registry...
}func newOptions(opts ...Option) Options {opt := Options{Broker:    broker.DefaultBroker,Registry:  registry.DefaultRegistry,...}for _, o := range opts {o(&opt)}return opt
}// Name of the service
func Name(n string) Option {return func(o *Options) {o.Server.Init(server.Name(n))}
}// Address sets the address of the server
func Address(addr string) Option {return func(o *Options) {o.Server.Init(server.Address(addr))}
}

現在,我們知道了如何實現函數默認參數,最重要的步驟如下👇

//定義結構體
type ExampleClient struct {Name stringJob string
}//定義配置選項函數(關鍵)
type Option func(*ExampleClient)
func SetName(name string) Option {// 返回一個Option類型的函數(閉包):接受ExampleClient類型指針參數并修改之return func(this *ExampleClient) {this.Name = name}
}//應用函數選項配置
func NewExampleClient(opts ...Option) ExampleClient{// 初始化默認值defaultClient := ExampleClient{Name: "default",Job:  "default",}// 依次調用opts函數列表中的函數,為結構體成員賦值for _, o := range opts {o(&defaultClient)}return defaultClient
}

這樣利用閉包的特性,當我們需要額外添加參數時,只需要增加配置選項函數即可,拓展性很強。
————————————————
版權聲明:本文為CSDN博主「johopig」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/zhetmdoubeizhanyong/article/details/106414205

我們看下用Functional Options Patter的方式,我寫了一個簡單的例子。

package mainimport "fmt"//如何向func傳遞默認值type dialOption struct {Username stringPassword stringService  string
}type DialOption interface {apply(*dialOption)
}type funcOption struct {f func(*dialOption)
}func(fdo *funcOption) apply(do *dialOption){fdo.f(do)
}func newFuncOption(f func(*dialOption))*funcOption{return &funcOption{f:f,}
}func withUserName(s string) DialOption{return  newFuncOption(func(o *dialOption){o.Username = s})
}func withPasswordd(s string) DialOption{return  newFuncOption(func(o *dialOption){o.Password = s})
}func withService(s string) DialOption{return  newFuncOption(func(o *dialOption){o.Service = s})
}//默認參數
func defaultOptions() dialOption{return dialOption{Service:"test",}
}type clientConn struct {timeout intdopts dialOption
}func NewClient(address string, opts ...DialOption){cc :=&clientConn{timeout:30,dopts:defaultOptions(),}//循環調用optsfor _,opt := range opts {opt.apply(&cc.dopts)}fmt.Printf("%+v",cc.dopts)
}func main(){NewClient("127.0.0.1",withPasswordd("654321"),withService("habox"))NewClient("127.0.0.1",withService("habox"))
}

實例化時,通過func的方式來傳遞參數,也可以定義一些默認參數。如果以后要加,只需要更改很少的代碼。
而且,這種方式也不會傳遞不相關的參數,因為參數都在通過func的方式來修改的。
唯一不好的地方可能是代碼量相應的增加了。但是為了更優雅,這種做法還是值得的。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/79061.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/79061.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/79061.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Chrome 136 H265 WebRTC 支持 正式版本已包含

時間過的真快,去年8月份寫過一篇文章介紹如何加參數方式啟動Chrome H265 硬件解碼器, 現在的136版本已經包含在內,至此WebRTC已經完整包含了H264和H265解碼器,這個事情應該從2015年開始,Google強推VP9 AV1&#xff0c…

12.SpringDoc OpenAPI 功能介紹(用于生成API接口文檔)

12.SpringDoc OpenAPI 功能介紹(用于生成API接口文檔) SpringDoc OpenAPI 是一個基于 OpenAPI 3.0/3.1 規范的工具,用于為 Spring Boot 應用生成 API 文檔。它是 springfox(Swagger 2.x)的現代替代方案,完全支持 Spring Boot 3.x…

CentOS Linux 環境二進制方式安裝 MySQL 5.7.32

文章目錄 安裝依賴包新建用戶解壓初始化配置文件啟動服務登錄MySQL修改密碼停止數據庫 安裝依賴包 yum -y install libaio perl perl-devel libncurses* autoconf numactl新建用戶 useradd mysql解壓 tar xf mysql-5.7.32-linux-glibc2.12-x86_64.tar.gz mv mysql-5.7.32-l…

Webug4.0通關筆記06- 第8關CSV注入

目錄 CSV注入漏洞 1.CSV漏洞簡介 2.漏洞原理 (1)公式執行 (2)DDE機制 (3)OS命令執行 3.漏洞防御 第08關 CSV注入 1.打開靶場 2.修改源碼 3.注入命令 4.導出excel表 5.打開excel表 CSV注入漏洞…

Windows和 macOS 上安裝 `nvm` 和 Node.js 16.16.0 的詳細教程。

Windows和 macOS 上安裝 nvm 和 Node.js 16.16.0 的詳細教程。 --- ### 1. 安裝 nvm(Node Version Manager) nvm 是一個 Node.js 版本管理工具,可以輕松安裝和切換不同版本的 Node.js。 #### Windows 安裝 nvm 1. **下載 nvm 安裝包**&#x…

[特殊字符] 藍橋杯省賽全解析:含金量、獲獎難度、參賽意義與發展價值全面剖析

藍橋杯省賽剛剛落幕,不論你是剛參加完比賽的同學,還是還在觀望是否值得投入時間去準備藍橋杯的學生,相信你都關心: 藍橋杯到底值不值得參加? 獲獎難不難?含金量如何? 和其它算法競賽相比有什么…

ASP.NET MVC后端控制器用模型 接收前端ajax數據為空

1、前端js代碼 如下: const formData {DeptName: D001,Phone: 12345678900 };$.ajax({url: "/Phone/SavePhone1",type: "POST",contentType: "application/json",data: JSON.stringify(formData), //必須要JSON.stringifysuccess:…

擁抱 Kotlin Flow

1. 引言 Kotlin Flow 是 Kotlin 協程生態中處理異步數據流的核心工具,它提供了一種聲明式、輕量級且與協程深度集成的響應式編程模型。與傳統的 RxJava 相比,Flow 更簡潔、更易于維護,尤其在 Android 開發中已成為主流選擇。本文將從基礎概念…

精益數據分析(34/126):深挖電商運營關鍵要點與指標

精益數據分析(34/126):深挖電商運營關鍵要點與指標 在創業和數據分析的學習之旅中,我們都在不斷探尋如何讓業務更上一層樓。今天,我依舊帶著和大家共同進步的想法,深入解讀《精益數據分析》中電商運營的關…

Learning vtkjs之ImageCropFilter

過濾器 圖片數據體積裁剪 介紹 vtkImageCropFilter可以裁剪vtkImageData。這只適用于IJK對齊的平面。 請注意,由于CPU限制的裁剪,這在大型數據集上會很慢。 效果 核心代碼 需要實現這個代碼主要邏輯 1、設定的crop的包圍盒 其實主要是IMax IMin JM…

深入理解 C++11 delete 關鍵字:禁用函數的藝術

一、什么是 delete 關鍵字 C11 引入的 delete 關鍵字是一種??顯式禁用函數??的語法機制。它允許開發者主動阻止特定函數的使用,比傳統的私有化聲明更直觀、更安全,且能在編譯期捕獲更多潛在錯誤。 二、為什么需要 delete? 1. 傳統方式…

深度剖析!GPT-image-1 API 開放對 AI 繪畫技術生態的沖擊!

4月24日凌晨,OpenAI正式發布了全新的圖像生成模型“gpt-image-1”,并通過API向全球開發者開放使用,這意味著其GPT-4o的圖像生成能力正式向開發者開放! 在這之前,GPT-4o的圖像生成功能于今年3月25日由 OpenAI 創始人兼 …

扣子流程圖批量導入飛書多維表格

文章目錄 整體結構分步驟進行處理1. 程序代碼處理2. 多維表格配置 整體結構 整個代碼塊結構如下: 首先,我們從其他流程中拿到一個數據列表,通過一個循環體,將每一個部分的內容都通過python代碼整理后,使用【插件】的…

【安全掃描器原理】端口掃描

【安全掃描器原理】端口掃描 1.端口掃描基本原理2.TCP掃描3.UDP掃描4.手工掃描1.端口掃描基本原理 以TCP端口為例,其原理是當一個主機向遠端一個服務器的某一個端口提出建立連接的請求,如果對方有此項服務,就會同意建立連接,如果對方未安裝此項服務時,則不會同意建立連接…

FastGPT部署的一些問題整理

在B站學習 圖靈程序員-諸葛 的LangChain快速入門課程之《部署FastGPT構建本地應用》。在我學習課程跟著老師實踐的過程中,踩了一些坑。這篇文章以問答的形式記錄一下學習中的一些問題,主要面向的讀者是,在學習同樣的課程的和部署FastGPT遇到各…

如何查看k8s獲取系統是否清理過docker鏡像

k8s集群某個節點down掉后,pod就會漂移到其他節點,但是在該節點卻又執行了拉取鏡像操作,明明該節點之前部署過該容器的,不知為什么又拉取了一次鏡像(鏡像拉取配置的優先使用本地),所以懷疑是觸發…

聚焦智能體未來,領馭科技在微軟創想未來峰會大放異彩

2025年4月23日,微軟創想未來峰會在北京中關村國際創新中心盛大舉行。作為微軟中國南區核心合作伙伴及HKCSP 1T首批授權云服務商,深圳領馭科技有限公司受邀參會,攜瀚鵬工業AI應用解決方案亮相峰會,與全球AI領袖及行業精英共話智能體…

元宇宙2.0:當區塊鏈成為數字世界的憲法

引言:當虛擬世界成為“新大陸” 清晨,你戴上VR設備進入一個由數字建筑構成的城市,這里的地皮屬于全球玩家,街邊的藝術品標著NFT認證碼,咖啡館里的人們用加密貨幣支付咖啡,而社區規則由持有代幣的居民投票決…

力扣hot100——239.滑動窗口最大值

題目鏈接: 239. 滑動窗口最大值 - 力扣(LeetCode) 優先級隊列 優先級隊列自動按照大小排序,隊首即為最大元素,但取隊首時要注意元素是否在滑動窗口內,如果不在則彈出。 class Solution { public:vector&…

Alibaba國際站商品詳情AP接口概述,json數據示例返回參考

前言 Alibaba國際站商品詳情API(通常稱為item_get接口)是阿里巴巴開放平臺提供的一項核心服務,允許開發者通過商品ID獲取商品的詳細信息。該接口廣泛應用于電商系統集成、數據分析、競品監控等場景,支持企業自動化獲取商品標題、…