11.14 结构体、集合和高阶函数

    然后我们就可以使用高阶函数,实际上也就是把函数作为定义所需方法(其他函数)的参数,例如:

    1)定义一个通用的 函数,它接收一个作用于每一辆 car 的 f 函数作参数:

    1. // Process all cars with the given function f:
    2. func (cs Cars) Process(f func(car *Car)) {
    3. for _, c := range cs {
    4. f(c)
    5. }
    6. }
    1. // Find all cars matching a given criteria.
    2. func (cs Cars) FindAll(f func(car *Car) bool) Cars {
    3. cars := make([]*Car, 0)
    4. cs.Process(func(c *Car) {
    5. if f(c) {
    6. cars = append(cars, c)
    7. }
    8. })
    9. return cars
    10. }

    3)实现 Map 功能,产出除 car 对象以外的东西:

    现在我们可以定义下面这样的具体查询:

    1. allNewBMWs := allCars.FindAll(func(car *Car) bool {
    2. return (car.Manufacturer == "BMW") && (car.BuildYear > 2010)
    3. })
    1. func MakeSortedAppender(manufacturers []string)(func(car *Car),map[string]Cars) {
    2. // Prepare maps of sorted cars.
    3. sortedCars := make(map[string]Cars)
    4. for _, m := range manufacturers {
    5. sortedCars[m] = make([]*Car, 0)
    6. }
    7. sortedCars["Default"] = make([]*Car, 0)
    8. // Prepare appender function:
    9. appender := func(c *Car) {
    10. if _, ok := sortedCars[c.Manufacturer]; ok {
    11. sortedCars[c.Manufacturer] = append(sortedCars[c.Manufacturer], c)
    12. } else {
    13. sortedCars["Default"] = append(sortedCars["Default"], c)
    14. }
    15. }
    16. return appender, sortedCars
    17. }

    现在我们可以用它把汽车分类为独立的集合,像这样:

    我们让这些代码在下面的程序 cars.go 中执行:

    1. // cars.go
    2. package main
    3. )
    4. type Any interface{}
    5. type Car struct {
    6. Model string
    7. Manufacturer string
    8. BuildYear int
    9. // ...
    10. }
    11. type Cars []*Car
    12. func main() {
    13. // make some cars:
    14. ford := &Car{"Fiesta", "Ford", 2008}
    15. bmw := &Car{"XL 450", "BMW", 2011}
    16. merc := &Car{"D600", "Mercedes", 2009}
    17. bmw2 := &Car{"X 800", "BMW", 2008}
    18. // query:
    19. allCars := Cars([]*Car{ford, bmw, merc, bmw2})
    20. allNewBMWs := allCars.FindAll(func(car *Car) bool {
    21. return (car.Manufacturer == "BMW") && (car.BuildYear > 2010)
    22. })
    23. fmt.Println("AllCars: ", allCars)
    24. fmt.Println("New BMWs: ", allNewBMWs)
    25. //
    26. manufacturers := []string{"Ford", "Aston Martin", "Land Rover", "BMW", "Jaguar"}
    27. sortedAppender, sortedCars := MakeSortedAppender(manufacturers)
    28. allCars.Process(sortedAppender)
    29. fmt.Println("Map sortedCars: ", sortedCars)
    30. BMWCount := len(sortedCars["BMW"])
    31. fmt.Println("We have ", BMWCount, " BMWs")
    32. }
    33. // Process all cars with the given function f:
    34. func (cs Cars) Process(f func(car *Car)) {
    35. for _, c := range cs {
    36. f(c)
    37. }
    38. }
    39. // Find all cars matching a given criteria.
    40. func (cs Cars) FindAll(f func(car *Car) bool) Cars {
    41. cs.Process(func(c *Car) {
    42. if f(c) {
    43. cars = append(cars, c)
    44. }
    45. })
    46. return cars
    47. }
    48. // Process cars and create new data.
    49. func (cs Cars) Map(f func(car *Car) Any) []Any {
    50. result := make([]Any, len(cs))
    51. ix := 0
    52. cs.Process(func(c *Car) {
    53. result[ix] = f(c)
    54. ix++
    55. })
    56. return result
    57. }
    58. func MakeSortedAppender(manufacturers []string) (func(car *Car), map[string]Cars) {
    59. // Prepare maps of sorted cars.
    60. sortedCars := make(map[string]Cars)
    61. for _, m := range manufacturers {
    62. sortedCars[m] = make([]*Car, 0)
    63. }
    64. sortedCars["Default"] = make([]*Car, 0)
    65. // Prepare appender function:
    66. appender := func(c *Car) {
    67. if _, ok := sortedCars[c.Manufacturer]; ok {
    68. sortedCars[c.Manufacturer] = append(sortedCars[c.Manufacturer], c)
    69. } else {
    70. sortedCars["Default"] = append(sortedCars["Default"], c)
    71. }
    72. }
    73. return appender, sortedCars
    74. }

    输出:

    1. AllCars: [0xf8400038a0 0xf840003bd0 0xf840003ba0 0xf840003b70]
    2. New BMWs: [0xf840003bd0]
    3. Map sortedCars: map[Default:[0xf840003ba0] Jaguar:[] Land Rover:[] BMW:[0xf840003bd0 0xf840003b70] Aston Martin:[] Ford:[0xf8400038a0]]
    4. We have 2 BMWs