1
0
mirror of https://github.com/chai2010/advanced-go-programming-book.git synced 2025-05-24 12:32:21 +00:00

Merge pull request #267 from fuwensun/pr1-4-1f

ch1-4-fix typo
This commit is contained in:
chai2010 2018-08-08 18:18:36 +08:00 committed by GitHub
commit b9f1439f59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -57,7 +57,7 @@ func Print(a ...interface{}) {
} }
``` ```
第一个`Print`调用时传入的参数是`a...`,等价于直接调用`Print(123, "abc")`。第二个`Print`调用传入的是解包的`a`,等价于直接调用`Print([]interface{}{123, "abc"})` 第一个`Print`调用时传入的参数是`a...`,等价于直接调用`Print(123, "abc")`。第二个`Print`调用传入的是解包的`a`,等价于直接调用`Print([]interface{}{123, "abc"})`
不仅函数的输入参数可以有名字,也可以给函数的返回值命名: 不仅函数的输入参数可以有名字,也可以给函数的返回值命名:
@ -114,7 +114,7 @@ func main() {
} }
``` ```
第一种方法是在循环体内部再定义一个局部变量,这样每次迭代`defer`语句的闭包函数捕获的都是不同的变量,这些变量的值对应迭代时的值。第二种方式是将迭代变量通过闭包函数的参数传入,`defer`语句会马上对调用参数求值。两种方式都是可以工作的。不过一般来说,在`for`循环内部执行`defer`语句并不是一个好的习惯,此处仅为示例,不建议使用 第一种方法是在循环体内部再定义一个局部变量,这样每次迭代`defer`语句的闭包函数捕获的都是不同的变量,这些变量的值对应迭代时的值。第二种方式是将迭代变量通过闭包函数的参数传入,`defer`语句会马上对调用参数求值。两种方式都是可以工作的。不过一般来说,在`for`循环内部执行`defer`语句并不是一个好的习惯,此处仅为示例,不建议使用
Go语言中如果以切片为参数调用函数时有时候会给人一种参数采用了传引用的方式的假象因为在被调用函数内部可以修改传入的切片的元素。其实任何可以通过函数参数修改调用参数的情形都是因为函数参数中显式或隐式传入了指针参数。函数参数传值的规范更准确说是只针对数据结构中固定的部分传值例如字符串或切片对应结构体中的指针和字符串长度结构体传值但是并不包含指针间接指向的内容。将切片类型的参数替换为类似`reflect.SliceHeader`结构体就很好理解切片传值的含义了: Go语言中如果以切片为参数调用函数时有时候会给人一种参数采用了传引用的方式的假象因为在被调用函数内部可以修改传入的切片的元素。其实任何可以通过函数参数修改调用参数的情形都是因为函数参数中显式或隐式传入了指针参数。函数参数传值的规范更准确说是只针对数据结构中固定的部分传值例如字符串或切片对应结构体中的指针和字符串长度结构体传值但是并不包含指针间接指向的内容。将切片类型的参数替换为类似`reflect.SliceHeader`结构体就很好理解切片传值的含义了:
@ -159,7 +159,7 @@ func g() int {
## 1.4.2 方法 ## 1.4.2 方法
方法一般是面向对象编程(OOP)的一个特性在C++语言中方法对应一个类对象的成员函数是关联到具体对象上的虚表中的。但是Go语言的方法却是关联到类型的这样可以在编译阶段完成方法的静态绑定。一个面向对象的程序会用方法来表达其属性对应的操作,这样使用这个对象的用户就不需要直接去操作对象,而是借助方法来做这些事情。面向对象编程(OOP)进入主流开发领域一般认为是从C++开始的C++就是在兼容C语言的基础之上支持了class等面向对象的特性。然后Java编程则号称是纯粹的面向对象语言因为Java中函数是不能独立存在的每个函数都必然是属于某个类的。 方法一般是面向对象编程(OOP)的一个特性在C++语言中方法对应一个类对象的成员函数是关联到具体对象上的虚表中的。但是Go语言的方法却是关联到类型的这样可以在编译阶段完成方法的静态绑定。一个面向对象的程序会用方法来表达其属性对应的操作这样使用这个对象的用户就不需要直接去操作对象而是借助方法来做这些事情。面向对象编程(OOP)进入主流开发领域一般认为是从C++开始的C++就是在兼容C语言的基础之上支持了class等面向对象的特性。然后Java编程则号称是纯粹的面向对象语言因为Java中函数是不能独立存在的每个函数都必然是属于某个类的。
面向对象编程更多的只是一种思想很多号称支持面向对象编程的语言只是将经常用到的特性内置到语言中了而已。Go语言的祖先C语言虽然不是一个支持面向对象的语言但是C语言的标准库中的File相关的函数也用到了的面向对象编程的思想。下面我们实现一组C语言风格的File函数 面向对象编程更多的只是一种思想很多号称支持面向对象编程的语言只是将经常用到的特性内置到语言中了而已。Go语言的祖先C语言虽然不是一个支持面向对象的语言但是C语言的标准库中的File相关的函数也用到了的面向对象编程的思想。下面我们实现一组C语言风格的File函数
@ -321,7 +321,7 @@ func (p *Cache) Lookup(key string) string {
## 1.4.3 接口 ## 1.4.3 接口
Go语言之父Rob Pike曾说过一句名言那些试图避免白痴行为的语言最终自己变成了白痴语言Languages that try to disallow idiocy become themselves idiotic。一般静态编程语言都有着严格的类型系统这使得编译器可以深入检查程序员没有作出什么出格的举动。但是过于严格的类型系统却会使得编程太过繁琐让程序员把大好的青春都浪费在了和编译器的斗争中。Go语言试图让程序员能在安全和灵活的编程之间取得一个平衡。它在提供严格的类型检查的同时通过接口类型实现了对鸭子类型的支持使得安全动态的编程变得相对容易。 Go语言之父Rob Pike曾说过一句名言那些试图避免白痴行为的语言最终自己变成了白痴语言Languages that try to disallow idiocy become themselves idiotic。一般静态编程语言都有着严格的类型系统这使得编译器可以深入检查程序员没有作出什么出格的举动。但是过于严格的类型系统却会使得编程太过繁琐让程序员把大好的青春都浪费在了和编译器的斗争中。Go语言试图让程序员能在安全和灵活的编程之间取得一个平衡。它在提供严格的类型检查的同时通过接口类型实现了对鸭子类型的支持使得安全动态的编程变得相对容易。
Go的接口类型是对其它类型行为的抽象和概括因为接口类型不会和特定的实现细节绑定在一起通过这种抽象的方式我们可以让对象更加灵活和更具有适应能力。很多面向对象的语言都有相似的接口概念但Go语言中接口类型的独特之处在于它是满足隐式实现的鸭子类型。所谓鸭子类型说的是只要走起路来像鸭子、叫起来也像鸭子那么就可以把它当作鸭子。Go语言中的面向对象就是如此如果一个对象只要看起来像是某种接口类型的实现那么它就可以作为该接口类型使用。这种设计可以让你创建一个新的接口类型满足已经存在的具体类型却不用去破坏这些类型原有的定义当我们使用的类型来自于不受我们控制的包时这种设计尤其灵活有用。Go语言的接口类型是延迟绑定可以实现类似虚函数的多态功能。 Go的接口类型是对其它类型行为的抽象和概括因为接口类型不会和特定的实现细节绑定在一起通过这种抽象的方式我们可以让对象更加灵活和更具有适应能力。很多面向对象的语言都有相似的接口概念但Go语言中接口类型的独特之处在于它是满足隐式实现的鸭子类型。所谓鸭子类型说的是只要走起路来像鸭子、叫起来也像鸭子那么就可以把它当作鸭子。Go语言中的面向对象就是如此如果一个对象只要看起来像是某种接口类型的实现那么它就可以作为该接口类型使用。这种设计可以让你创建一个新的接口类型满足已经存在的具体类型却不用去破坏这些类型原有的定义当我们使用的类型来自于不受我们控制的包时这种设计尤其灵活有用。Go语言的接口类型是延迟绑定可以实现类似虚函数的多态功能。