程式語言學習如果只碰語法,很難感受到學習的樂趣。這篇文章將從日常「去超市買水果」的生活例子展開,帶你循序漸進地理解 Go 的 slice、map、for 迴圈、struct、interface 等核心訊息,並在過程中逐步加入越來越複雜的業務邏輯挑戰,讓學習更有成就感與實戰感。
首先,我們要為「商品」設計一個 struct,包括名字、價格、數量。再利用 slice 來表示購物籃,裡面裝著每一樣買的商品。
type Product struct {
Name string
Price int
Qty int
}
func main() {
basket := []Product{
{"Apple", 10, 3},
{"Banana", 5, 6},
{"Watermelon", 50, 1},
}
fmt.Println("購物籃:", basket)
}
此時購物籃是有序的商品列表,我們可以用 for
迴圈逐項處理:
total := 0
for _, item := range basket {
total += item.Price * item.Qty
fmt.Printf("買了 %d 個 %s,單價 %d\n", item.Qty, item.Name, item.Price)
}
fmt.Println("總金額:", total)
在超市,價格表經常用來查找商品的單價。我們用 map[string]int 來表示。
當顧客再次購買同一商品時,不是新增一個商品,而是更新數量。以下示範如何用 slice + for 搭配實現查找和更新:
priceList := map[string]int{
"Apple": 10,
"Banana": 5,
"Milk": 30,
}
func addOrUpdateCart(cart []Product, prod Product) []Product {
for i, item := range cart {
if item.Name == prod.Name {
cart[i].Qty += prod.Qty
return cart
}
}
return append(cart, prod)
}
func main() {
cart := []Product{}
cart = addOrUpdateCart(cart, Product{"Apple", priceList["Apple"], 3})
cart = addOrUpdateCart(cart, Product{"Banana", priceList["Banana"], 2})
cart = addOrUpdateCart(cart, Product{"Apple", priceList["Apple"], 2}) // 更新 Apple 數量
fmt.Println(cart)
}
這讓我們實作了更接近真實購物情境的商品更新。
假設商店有促銷清單,只打折促銷商品,我們需掃描購物籃並比對促銷清單,計算折扣後的價格。
promoList := []string{"Apple", "Milk"}
for _, prod := range cart {
discount := 0.0
for _, promoItem := range promoList {
if prod.Name == promoItem {
discount = 0.1 // 10% 折扣
break
}
}
priceAfterDiscount := int(float64(prod.Price) * (1 - discount))
fmt.Printf("%s 原價 %d,折扣後 %d\n", prod.Name, prod.Price, priceAfterDiscount)
}
巢狀迴圈幫助實現了促銷商品的比對,讓程式更靈活能面對複雜業務。
不同類別商品(水果、飲料、零食)可能有不同計價邏輯。我們用 interface 抽象「結帳物件」:
type Checkoutable interface {
Total() int
}
type Product struct {
Name string
Price int
Qty int
Discount float64
}
func (p Product) Total() int {
return int(float64(p.Price)*(1-p.Discount)) * p.Qty
}
type Drink struct {
Name string
Price int
Qty int
Size string // 不同容量,不同價格策略
}
func (d Drink) Total() int {
// 比如大杯多 10 元
extra := 0
if d.Size == "Large" {
extra = 10
}
return (d.Price + extra) * d.Qty
}
func main() {
var cart []Checkoutable
cart = append(cart, Product{"Apple", 10, 3, 0.1})
cart = append(cart, Drink{"Cola", 15, 2, "Large"})
total := 0
for _, item := range cart {
total += item.Total()
}
fmt.Println("總金額:", total)
}
這樣購物籃可以裝不同商品,也能用同一種方式結帳。
最後,我們設計一個交易系統,支援多賣家,多筆購買紀錄與不同付款方式:
type Purchase struct {
Item Checkoutable
Shop string
}
type PaymentMethod interface {
Pay(amount int)
}
type CreditCard struct{ Number string }
func (c CreditCard) Pay(amount int) {
fmt.Printf("使用信用卡付款 %d 元,卡號 %s\n", amount, c.Number)
}
type Cash struct{}
func (c Cash) Pay(amount int) {
fmt.Printf("使用現金付款 %d 元\n", amount)
}
func main() {
purchases := map[string][]Purchase{
"FreshMart": {
{Product{"Apple", 10, 5, 0.1}, "FreshMart"},
{Product{"Milk", 30, 1, 0}, "FreshMart"},
},
"SuperShop": {
{Drink{"Cola", 15, 2, "Large"}, "SuperShop"},
},
}
total := 0
for _, records := range purchases {
for _, p := range records {
total += p.Item.Total()
}
}
var payMethod PaymentMethod = CreditCard{"1234-5678-9876-5432"}
payMethod.Pay(total)
}
交易清楚紀錄每家賣家的購買明細,付款方式彈性可擴展。