Golang 高階函數
定義
高階函數是接收函數作為參數或返回函數作為輸出的函數。
高階函數是對其他函數進行操作的函數,要麼將它們作為參數,要麼返回它們。
舉例
函數作為參數
package main
import "fmt"
func sum(x, y int) int {
return x + y
}
func process(x int, y int, f func(int, int) int) int {
return f(x, y)
}
func main() {
x, y := 1, 2
fmt.Println(process(x, y, sum))
}
輸出結果
3
函數作為返回值
package main
import "fmt"
func addPrefix(str string) string {
return "prefix_" + str
}
func addSuffix(str string) string {
return str + "_suffix"
}
func process(idx int) func(string) string {
switch idx {
case 1:
return addPrefix
case 2:
return addSuffix
default:
return addPrefix
}
}
func main() {
need_prefix := []string{"aaa", "bbb", "ccc"}
need_suffix := []string{"AAA", "BBB", "CCC"}
prefix_f := process(1)
suffix_f := process(2)
for i, v := range need_prefix {
need_prefix[i] = prefix_f(v)
}
for i, v := range need_suffix {
need_suffix[i] = suffix_f(v)
}
fmt.Println("need_prefix:", need_prefix)
fmt.Println("need_suffix:", need_suffix)
}
輸出結果
need_prefix: [prefix_aaa prefix_bbb prefix_ccc]
need_suffix: [AAA_suffix BBB_suffix CCC_suffix]
兩者結合起來
衣服,交通工具,水果分類
定義一個結構體
type Commodity struct {
Name string
Type string
}
type Cds []*Commodity
自定義結構體的String()
先看一下沒有自定義結構體的String(),打印出來的結果
[0xc0000ba000 0xc0000ba020 0xc0000ba040 0xc0000ba060 0xc0000ba080 0xc0000ba0a0]
map[clothes:[] fruit:[] others:[] transportation:[]]
map[clothes:[0xc0000ba080 0xc0000ba0a0] fruit:[0xc0000ba000 0xc0000ba020] others:[] transportation:[0xc0000ba040 0xc0000ba060]]
all fruit: [0xc0000ba000 0xc0000ba020]
全都是地址,所以我們需要實現自定義結構體的String()
func (cd *Commodity) String() string {
return cd.Type + "," + cd.Name
}
func (cds Cds) String() string {
var result string
for _, v := range cds {
// result = append(result, v.String()...)
result += v.String() + " | "
}
return result
}
再看下打印結果,順眼多了
fruit,apple | fruit,banana | transportation,car | transportation,bike | clothes,T-shirt | clothes,skirt |
map[clothes: fruit: others: transportation:]
map[clothes:clothes,T-shirt | clothes,skirt | fruit:fruit,apple | fruit,banana | others: transportation:transportation,car | transportation,bike | ]
all fruit: fruit,apple | fruit,banana |
定一個函數,參數是用來處理每一個結構體函數,這樣可以省去我們多次的for
遍歷
func (cds Cds) process(f func(cd *Commodity)) {
for _, v := range cds {
f(v)
}
}
正常情況下我們的輸入是一串沒有區分類別的數據,這種情況下我們肯定是需要去做分類的,所以我們定義個自動分類的函數
func classifier(types []string) (func(cd *Commodity), map[string]Cds) {
result := make(map[string]Cds)
for _, v := range types {
result[v] = make(Cds, 0)
}
result["others"] = make(Cds, 0)
appender := func(cd *Commodity) {
if _, ok := result[cd.Type]; ok {
result[cd.Type] = append(result[cd.Type], cd)
} else {
result["others"] = append(result["others"], cd)
}
}
return appender, result
}
除了分類後,我們有時候可能需要在一大堆未分類的數據中找到我們需要的某一種類型,所以我們還需要定義一個查找函數
func (cds Cds) findType(f func(cd *Commodity) bool) Cds {
result := make(Cds, 0)
cds.process(func(c *Commodity) {
if f(c) {
result = append(result, c)
}
})
return result
}
完整代碼
package main
import "fmt"
type Commodity struct {
Name string
Type string
}
type Cds []*Commodity
func (cd *Commodity) String() string {
return cd.Type + "," + cd.Name
}
func (cds Cds) String() string {
var result string
for _, v := range cds {
// result = append(result, v.String()...)
result += v.String() + " | "
}
return result
}
func main() {
fruit1 := Commodity{"apple", "fruit"}
fruit2 := Commodity{"banana", "fruit"}
transportation1 := Commodity{"car", "transportation"}
transportation2 := Commodity{"bike", "transportation"}
clothes1 := Commodity{"T-shirt", "clothes"}
clothes2 := Commodity{"skirt", "clothes"}
all_commodity := Cds([]*Commodity{&fruit1, &fruit2,
&transportation1, &transportation2,
&clothes1, &clothes2})
fmt.Println(all_commodity)
types := []string{"fruit", "transportation", "clothes"}
appender, cds := classifier(types)
fmt.Println(cds)
all_commodity.process(appender)
fmt.Println(cds)
all_fruit := all_commodity.findType(func(cd *Commodity) bool {
return cd.Type == "fruit"
})
fmt.Println("all fruit:", all_fruit)
}
func (cds Cds) process(f func(cd *Commodity)) {
for _, v := range cds {
f(v)
}
}
func (cds Cds) findType(f func(cd *Commodity) bool) Cds {
result := make(Cds, 0)
cds.process(func(c *Commodity) {
if f(c) {
result = append(result, c)
}
})
return result
}
func classifier(types []string) (func(cd *Commodity), map[string]Cds) {
result := make(map[string]Cds)
for _, v := range types {
result[v] = make(Cds, 0)
}
result["others"] = make(Cds, 0)
appender := func(cd *Commodity) {
if _, ok := result[cd.Type]; ok {
result[cd.Type] = append(result[cd.Type], cd)
} else {
result["others"] = append(result["others"], cd)
}
}
return appender, result
}
輸出結果
fruit,apple | fruit,banana | transportation,car | transportation,bike | clothes,T-shirt | clothes,skirt |
map[clothes: fruit: others: transportation:]
map[clothes:clothes,T-shirt | clothes,skirt | fruit:fruit,apple | fruit,banana | others: transportation:transportation,car | transportation,bike | ]
all fruit: fruit,apple | fruit,banana |