首頁 > 軟體

教你利用Golang可選引數實現可選模式

2023-01-31 06:01:26

本文討論Golang函數可選引數及函數型別,以及如何利用可選函數型別實現可選模式。同時通過建構函式作為範例,實現強大帶可選引數的建構函式,讓程式碼更直觀、靈活、支援擴充套件。

從需求開始

可選引數給函數傳遞額外引數擴充套件或修改其行為,下面範例利用可選功能建立House型別:

h := NewHouse(
  WithConcrete(),
  WithoutFireplace(),
)

NewHouse是建構函式,WithConcreteWithoutFireplace是傳入建構函式的可選引數,用於修改其返回值。下面會詳細WithConcreteWithoutFireplace可選功能函數,有時它們比正常函數引數更有用。

定義建構函式

首先定義要利用可選功能的結構體:

type House struct {
	Material     string
	HasFireplace bool
	Floors       int
}

// `NewHouse` is a constructor function for `*House`
func NewHouse() *House {
	const (
		defaultFloors       = 2
		defaultHasFireplace = true
		defaultMaterial     = "wood"
	)

	h := &House{
		Material:     defaultMaterial,
		HasFireplace: defaultHasFireplace,
		Floors:       defaultFloors,
	}

	return h
}

House可能採用不同材料,有多層,並可能包括壁爐。NewHouse建構函式返回House指標,所有屬性包括預設值。正常情況下,首先構造House,然後根據不同需求修改屬性值。使用函數可選引數,可以給建構函式傳入一組修改器函數。

定義可選函數

首先定義函數型別,接受House型別指標:

type HouseOption func(*House)

這是可選函數的簽名,下面定義一些可選函數用於修改*House範例:

func WithConcrete() HouseOption {
	return func(h *House) {
		h.Material = "concrete"
	}
}

func WithoutFireplace() HouseOption {
	return func(h *House) {
		h.HasFireplace = false
	}
}

上面每個函數是可選建構函式,返回另一個函數,帶*House引數,沒有返回值。我們看到返回的函數修改了*House範例的屬性。還可以實現其他可選函數型別用於修改引數範例屬性,下面函數返回修改樓層的可選函數:

func WithFloors(floors int) HouseOption {
	return func(h *House) {
		h.Floors = floors
	}
}

增強建構函式

現在組合可選功能函數和建構函式:

// NewHouse now takes a slice of option as the rest arguments
func NewHouse(opts ...HouseOption) *House {
	const (
		defaultFloors       = 2
		defaultHasFireplace = true
		defaultMaterial     = "wood"
	)

	h := &House{
		Material:     defaultMaterial,
		HasFireplace: defaultHasFireplace,
		Floors:       defaultFloors,
	}

	// Loop through each option
	for _, opt := range opts {
		// Call the option giving the instantiated
		// *House as the argument
		opt(h)
	}

	// return the modified house instance
	return h
}

建構函式接受一組任意數量可選功能函數作為引數,首次初始化House屬性後,依此執行可選功能函數修改屬性值。
回到開始的範例,現在可以實現帶可選引數的建構函式呼叫:

h := NewHouse(
  WithConcrete(),
  WithoutFireplace(),
  WithFloors(3),
)

可選模式的優勢

上面討論瞭如何實現可選模式,這裡總結下其優勢。

直觀清晰

相比於顯示修改物件屬性:

h := NewHouse()
h.Material = "concrete"

可利用建構函式直接實現:

h := NewHouse(WithConcrete())

採用這種方式更清晰,無需指定字串值,避免打字錯誤並暴露*House內部細節。

支援擴充套件

可選模式支援擴充套件,總是支援不同可選函數引數傳入建構函式。舉例,既然房屋樓層可以為任何整數,我們提供具體數值作為引數傳入建構函式:

h := NewHouse(WithFloors(4))

引數順序

使用可選模式與引數順序無關,相比於正常引數有很大的靈活性;而且,可以提供任意個可選引數,相比正常引數則必須提供所有引數。

// What `NewHouse` would look like if we used
// regular function arguments
// We would always need to provide all three
// arguments no matter what
h := NewHouse("concrete", 5, true)

到此這篇關於利用Golang可選引數實現可選模式的文章就介紹到這了,更多相關Golang可選引數內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com