From 858170db37733931f04491a2f01089b7e0647fe1 Mon Sep 17 00:00:00 2001 From: dake Date: Mon, 2 Nov 2015 22:25:22 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E7=BF=BB=E8=AF=91=2011.13?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eBook/11.13.md | 22 ++++++++++++++++++++++ eBook/11.14.md | 2 ++ 2 files changed, 24 insertions(+) create mode 100644 eBook/11.14.md diff --git a/eBook/11.13.md b/eBook/11.13.md index b0b9d33..30939a5 100644 --- a/eBook/11.13.md +++ b/eBook/11.13.md @@ -1,2 +1,24 @@ # 总结:Go 中的面向对象 +我们总结一下前面看到的:Go 没有类,而是松耦合的类型、方法对接口的实现。 + +OO 语言最重要的三个方面分别是:封装,继承和多态,在 Go 中它们是怎样表现的呢? + +- 封装(数据隐藏):和别的 OO 语言有 4 个或更多的访问层次相比,Go 把它简化为了 2 层(参见 4.2 节的可见性规则): + + 1)包范围内的:通过标识符首字母小写,`对象`只在它所在的包内可见 + + 2)可导出的:通过标识符首字母大写,`对象`在所在包以外可见 + +类型只拥有自己所在包中定义的方法。 + +- 继承:用组合实现:内嵌一个(或多个)包含想要行为(字段和方法)的类型;多重继承可以通过内嵌多个类型实现 + +- 多态:用接口实现:某个类型的实例可以赋给它实现的任意接口的变量。类型和接口是松耦合的,并且多重继承可以通过实现多个接口达到。Go 接口不是 Java 和 C# 接口的变体,而且:接口间是不相关的,并且是大规模编程和可适应演进型设计的关键。 + + +## 链接 + +- [目录](directory.md) +- 上一节:[接口与动态类型](11.12.md) +- 下一节:[结构体,集合和高阶函数](11.14.md) \ No newline at end of file diff --git a/eBook/11.14.md b/eBook/11.14.md new file mode 100644 index 0000000..de5168f --- /dev/null +++ b/eBook/11.14.md @@ -0,0 +1,2 @@ +# 结构体,集合和高阶函数 + From cbdb2d70ceb6a6b00ab143216d7bd73a8b361d9e Mon Sep 17 00:00:00 2001 From: dake Date: Mon, 2 Nov 2015 23:32:53 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E7=BF=BB=E8=AF=9111.14?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eBook/11.13.md | 6 +- eBook/11.14.md | 214 +++++++++++++++++++++++++++++++++++++++++++++ eBook/directory.md | 1 + 3 files changed, 218 insertions(+), 3 deletions(-) diff --git a/eBook/11.13.md b/eBook/11.13.md index 30939a5..afe1d04 100644 --- a/eBook/11.13.md +++ b/eBook/11.13.md @@ -8,13 +8,13 @@ OO 语言最重要的三个方面分别是:封装,继承和多态,在 Go 1)包范围内的:通过标识符首字母小写,`对象`只在它所在的包内可见 - 2)可导出的:通过标识符首字母大写,`对象`在所在包以外可见 + 2)可导出的:通过标识符首字母大写,`对象`对所在包以外也可见 类型只拥有自己所在包中定义的方法。 -- 继承:用组合实现:内嵌一个(或多个)包含想要行为(字段和方法)的类型;多重继承可以通过内嵌多个类型实现 +- 继承:用组合实现:内嵌一个(或多个)包含想要的行为(字段和方法)的类型;多重继承可以通过内嵌多个类型实现 -- 多态:用接口实现:某个类型的实例可以赋给它实现的任意接口的变量。类型和接口是松耦合的,并且多重继承可以通过实现多个接口达到。Go 接口不是 Java 和 C# 接口的变体,而且:接口间是不相关的,并且是大规模编程和可适应演进型设计的关键。 +- 多态:用接口实现:某个类型的实例可以赋给它所实现的任意接口类型的变量。类型和接口是松耦合的,并且多重继承可以通过实现多个接口实现。Go 接口不是 Java 和 C# 接口的变体,而且:接口间是不相关的,并且是大规模编程和可适应的演进型设计的关键。 ## 链接 diff --git a/eBook/11.14.md b/eBook/11.14.md index de5168f..ba44e1d 100644 --- a/eBook/11.14.md +++ b/eBook/11.14.md @@ -1,2 +1,216 @@ # 结构体,集合和高阶函数 +通常你在应用中定义了一个结构体,那么你也可能需要这个结构体的(指针)对象集合,比如: + +```go +type Any interface{} +type Car struct { + Model string + Manufacturer string + BuildYear int + // ... +} + +type Cars []*Car + +``` + +我们可以用函数定义所需的功能有争议的事实来使用高阶函数,例如: + +1)定义一个通用的 `Process()` 函数,它接收一个作用于每一辆 car 的 f 函数作参数: + +```go +// Process all cars with the given function f: +func (cs Cars) Process(f func(car *Car)) { + for _, c := range cs { + f(c) + } +} + +``` + +2)在上面的基础上,实现一个查找函数来获取子集合,并在 `Process()` 中传入一个闭包执行(这样就可以访问局部切片 `cars`): + +```go +// Find all cars matching a given criteria. +func (cs Cars) FindAll(f func(car *Car) bool) Cars { + + cars := make([]*Car, 0) + cs.Process(func(c *Car) { + if f(c) { + append(cars,c) + } + ) + return cars +} + +``` + +3)实现一个 Map 功能,产出除了 car 对象以外的东西: + +```go +// Process cars and create new data. +func (cs Cars) Map(f func(car *Car) Any) []Any { + result := make([]Any, 0) + ix := 0 + cs.Process(func(c *Car) { + result[ix] = f(c) + ix++ + }) + return result +} + +``` + +现在我们可以定义下面这样的具体查询: + +```go +allNewBMWs := allCars.FindAll(func(car *Car) bool { + return (car.Manufacturer == “BMW”) && (car.BuildYear > 2010) +}) + +``` + +4)我们也可以根据入参返回不同的函数。也许我们想根据不同的厂商添加汽车到不同的集合,但是这可能会是多变的。所以我们可以定义一个函数来产生特定的添加函数和 map 集: + +```go +funcMakeSortedAppender(manufacturers[]string)(func(car*Car),map[string]Cars) { + // Prepare maps of sorted cars. + sortedCars := make(map[string]Cars) + for _, m := range manufacturers { + sortedCars[m] = make([]*Car, 0) + } + sortedCars[“Default”] = make([]*Car, 0) + // Prepare appender function: + appender := func(c *Car) { + if _, ok := sortedCars[c.Manufacturer]; ok { + sortedCars[c.Manufacturer] = append(sortedCars[c.Manufacturer], c) + } else { + sortedCars[“Default”] = append(sortedCars[“Default”], c) + } + + } + return appender, sortedCars +} + +``` + +现在我们可以用它来把汽车分为独立的集合,像这样: + +```go +manufacturers := []string{“Ford”, “Aston Martin”, “Land Rover”, “BMW”, “Jaguar”} +sortedAppender, sortedCars := MakeSortedAppender(manufacturers) +allUnsortedCars.Process(sortedAppender) +BMWCount := len(sortedCars[“BMW”]) + +``` + +我们让这些代码在下面的程序 cars.go(此外只展示了 main() 中的代码,别的代码已经在上面展示)中执行: + +示例 11.18 [cars.go](examples/chapter_11/cars.go): + +```go +// cars.go +package main + +import ( + "fmt" +) + + +type Any interface{} +type Car struct { + Model string + Manufacturer string + BuildYear int + // ... +} +type Cars []*Car + +func main() { + // make some cars: + ford := &Car{"Fiesta","Ford", 2008} + bmw := &Car{"XL 450", "BMW", 2011} + merc := &Car{"D600", "Mercedes", 2009} + bmw2 := &Car{"X 800", "BMW", 2008} + // query: + allCars := Cars([]*Car{ford, bmw, merc, bmw2}) + allNewBMWs := allCars.FindAll(func(car *Car) bool { + return (car.Manufacturer == "BMW") && (car.BuildYear > 2010) + }) + fmt.Println("AllCars: ", allCars) + fmt.Println("New BMWs: ", allNewBMWs) + // + manufacturers := []string{"Ford", "Aston Martin", "Land Rover", "BMW", "Jaguar"} + sortedAppender, sortedCars := MakeSortedAppender(manufacturers) + allCars.Process(sortedAppender) + fmt.Println("Map sortedCars: ", sortedCars) + BMWCount := len(sortedCars["BMW"]) + fmt.Println("We have ", BMWCount, " BMWs") +} + +// Process all cars with the given function f: +func (cs Cars) Process(f func(car *Car)) { + for _, c := range cs { + f(c) + } +} + +// Find all cars matching a given criteria. +func (cs Cars) FindAll(f func(car *Car) bool) Cars { + cars := make([]*Car, 0) + + cs.Process(func(c *Car) { + if f(c) { + cars = append(cars, c) + } + }) + return cars +} + +// Process cars and create new data. +func (cs Cars) Map(f func(car *Car) Any) []Any { + result := make([]Any, 0) + ix := 0 + cs.Process(func(c *Car) { + result[ix] = f(c) + ix++ + }) + return result +} + +func MakeSortedAppender(manufacturers []string) (func(car *Car), map[string]Cars) { + // Prepare maps of sorted cars. + sortedCars := make(map[string]Cars) + + for _, m := range manufacturers { + sortedCars[m] = make([]*Car, 0) + } + sortedCars["Default"] = make([]*Car, 0) + + // Prepare appender function: + appender := func(c *Car) { + if _, ok := sortedCars[c.Manufacturer]; ok { + sortedCars[c.Manufacturer] = append(sortedCars[c.Manufacturer], c) + } else { + sortedCars["Default"] = append(sortedCars["Default"], c) + } + } + return appender, sortedCars +} + +/* Output: +AllCars: [0xf8400038a0 0xf840003bd0 0xf840003ba0 0xf840003b70] +New BMWs: [0xf840003bd0] +Map sortedCars: map[Default:[0xf840003ba0] Jaguar:[] Land Rover:[] BMW:[0xf840003bd0 0xf840003b70] Aston Martin:[] Ford:[0xf8400038a0]] +We have 2 BMWs +*/ + +``` + + +## 链接 + +- [目录](directory.md) +- 上一节:[Go 中的面向对象](11.13.md) +- 下一章:[读写数据](12.0.md) \ No newline at end of file diff --git a/eBook/directory.md b/eBook/directory.md index 15939cf..ac28c10 100644 --- a/eBook/directory.md +++ b/eBook/directory.md @@ -107,6 +107,7 @@ - 11.11 [Printf 和反射](11.11.md) - 11.12 [接口与动态类型](11.12.md) - 11.13 [总结:Go 中的面向对象](11.13.md) + - 11.14 [结构体,集合和高阶函数](11.14.md) ## 第三部分:Go 高级编程 From 7ca34089ef2d49e09490b236849a014b2b0a8ee2 Mon Sep 17 00:00:00 2001 From: dake Date: Mon, 2 Nov 2015 23:47:44 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=A0=A1=E5=AF=B911.14?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eBook/11.14.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/eBook/11.14.md b/eBook/11.14.md index ba44e1d..a13ce6c 100644 --- a/eBook/11.14.md +++ b/eBook/11.14.md @@ -15,7 +15,7 @@ type Cars []*Car ``` -我们可以用函数定义所需的功能有争议的事实来使用高阶函数,例如: +在定义所需功能时我们可以利用函数可以作为(其它函数的)参数的事实来使用高阶函数,例如: 1)定义一个通用的 `Process()` 函数,它接收一个作用于每一辆 car 的 f 函数作参数: @@ -46,7 +46,7 @@ func (cs Cars) FindAll(f func(car *Car) bool) Cars { ``` -3)实现一个 Map 功能,产出除了 car 对象以外的东西: +3)实现 Map 功能,产出除 car 对象以外的东西: ```go // Process cars and create new data. @@ -95,7 +95,7 @@ funcMakeSortedAppender(manufacturers[]string)(func(car*Car),map[string]Cars) { ``` -现在我们可以用它来把汽车分为独立的集合,像这样: +现在我们可以用它把汽车分类为独立的集合,像这样: ```go manufacturers := []string{“Ford”, “Aston Martin”, “Land Rover”, “BMW”, “Jaguar”} @@ -105,7 +105,7 @@ BMWCount := len(sortedCars[“BMW”]) ``` -我们让这些代码在下面的程序 cars.go(此外只展示了 main() 中的代码,别的代码已经在上面展示)中执行: +我们让这些代码在下面的程序 cars.go(此处只展示了 main() 中的代码,别的代码已经在上面展示)中执行: 示例 11.18 [cars.go](examples/chapter_11/cars.go):