在 Golang 中,管理程式碼邏輯的核心在於簡潔與清晰,這不僅提高了程式碼的可讀性,也提升了可維護性。本教學將探討如何撰寫小而精的函數以及如何合理處理參數,並理解 Golang 的包(Package)與命名規則。
// FIXME: - 不好的範例:
func CreateUser(name string, age int, email string, address string, phoneNumber string) {
// 處理使用者創建
}
// TODO: - 優化後的範例:
type User struct {
Name string
Age int
Email string
Address string
PhoneNumber string
}
func CreateUser(user User) {
// 處理使用者創建
}
使用
struct
讓參數結構清晰,未來也可以輕鬆擴展User
的屬性。
在 Go 語言中,除了定義命名函數外,還可以使用匿名函數(Anonymous Functions)來實現更靈活的程式設計。當匿名函數定義完成後,可以立即執行它
,這種模式稱為 立即執行函數(Immediately Invoked Function Expression, IIFE)。
特點:
無參數的 IIFE
func() {
fmt.Println("Hello")
}()
定義了一個無參數的匿名函數,並在定義後立即使用
()
執行它。
func(name string, age int) {
fmt.Printf("姓名: %s, 年齡: %d\n", name, age)
}("Alice", 30)
定義了一個接受
name
和age
兩個參數的匿名函數,並傳入"Alice"
和30
作為實際參數。
result := func(a, b int) int {
return a + b
}(5, 7)
fmt.Println("5 + 7 =", result)
定義了一個接受兩個整數參數並回傳其和的匿名函數,立即傳入 5 和 7 執行,並將結果存入變數
result
。
高層模組應該依賴於抽象,而不是依賴具體實現。
抽象(介面或抽象類別)不應依賴具體實作,反而具體實作應依賴抽象。
高層模組應該依賴於抽象
package main
import "fmt"
// 定義 PaymentProcessor 介面
type PaymentProcessor interface {
ProcessPayment(amount float64) bool
}
// CreditCardProcessor 實作信用卡付款
type CreditCardProcessor struct{}
func (cc CreditCardProcessor) ProcessPayment(amount float64) bool {
fmt.Printf("信用卡付款:$%.2f\n", amount)
return true
}
// PayPalProcessor 實作 PayPal 付款
type PayPalProcessor struct{}
func (pp PayPalProcessor) ProcessPayment(amount float64) bool {
fmt.Printf("PayPal 付款:$%.2f\n", amount)
return true
}
// DaiwanPayProcessor 實作 台灣Pay 付款
type DaiwanPayProcessor struct{}
func (bp DaiwanPayProcessor) ProcessPayment(amount float64) bool {
fmt.Printf("台灣Pay 付款:$%.2f\n", amount)
return true
}
// MakePayment 根據 PaymentProcessor 來處理付款
func MakePayment(p PaymentProcessor, amount float64) {
success := p.ProcessPayment(amount)
if success {
fmt.Println("付款成功!")
} else {
fmt.Println("付款失敗!")
}
}
func main() {
// 信用卡付款
creditCardProcessor := CreditCardProcessor{}
MakePayment(creditCardProcessor, 100.0)
// PayPal 付款
paypalProcessor := PayPalProcessor{}
MakePayment(paypalProcessor, 200.0)
// 台灣Pay 付款
DaiwanPayProcessor := DaiwanPayProcessor{}
MakePayment(DaiwanPayProcessor, 300.0)
}
</* Output: */>
信用卡付款:$100.00
付款成功!
PayPal 付款:$200.00
付款成功!
台灣Pay 付款:$300.00
付款成功!
MakePayment
是高層模組,它並沒有依賴具體的付款實現如CreditCardProcessor
、PayPalProcessor
或DaiwanPayProcessor
,而是依賴於PaymentProcessor
介面。
這樣的設計使得程式碼更加靈活,能夠輕鬆切換或擴展不同的付款方式,而不需要修改高層邏輯(MakePayment
函數)。
Go 語言中,變數或函數是否可以被其他 package 存取,並不依靠
public
或private
關鍵字,而是根據命名的第一個字母大小寫來決定:
- 大寫開頭的函數、變數和類型可以被其他 package 存取(Public)。
- 小寫開頭的函數、變數和類型則只能在相同 package 內使用(Private)。
// Public
var PublicVariable string
type PublicStruct struct {}
func PublicFunction() {}
// Private
var privateVariable string
type privateStruct struct {}
func privateFunction() {}
myproject/
├── main.go
└── math/
└── math.go
math.go
package math
// 公開的 Add 函數,可以被其他 package 匯入並使用
func Add(a int, b int) int {
return a + b
}
main.go
package main
import (
"fmt"
"myproject/math" // 匯入自定義的 math package
)
func main() {
result := math.Add(10, 5) // 使用 math package 中的 Add 函數
fmt.Println("結果:", result)
}
- 上面的
myproject
是我們在go.mod
定義的模組名稱(如果忘記的話,可以去複習第二天的內容),他後面接的就是在我們專案資料夾下面
我們檔案所處在的資料夾路徑
。- 在 Go 語言中,package 是程式碼的基本組織單位。
不同的 package 之間,只能存取大寫開頭的公開成員
(即public
成員)。這些公開成員包括函數、變數和結構體。
如果成員名稱是小寫開頭的
,則這些成員僅能在相同的 package 中存取
(即private
成員),其他 package 無法直接使用它們。
今天我們學到了以下幾點: