Go 学习笔记4 抽象方法
Go 学习笔记4 抽象模式
Go 的抽象方法主要通过函数、方法和接口三种方式。
函数,Function
Go 中函数是一等公民,可以被传递、返回,具有类型,是组织程序的基本元素。
1 | func name(params-list) (returns-list) { |
returns-list 是可选的,但是如果写明,则函数内部构造局部变量,并且会被返回。
1 | funcsub(x,yint)(zint) {z=x-y;return} // 注意这里需要 return 关键字,但是不需要 z |
Go 的函数参数没有默认值,参数的名字也不重要。( hmm 会不会很不方便?)函数全部是 call by value,即复制传入参数。
Go 递归函数的深度可以非常深,call stack 可以达到几个G大小。
Go 的函数支持多值返回。(很方便,而且返回值和状态是常用模式)
Go 的函数没有异常捕捉机制,而是显式采用 error 处理,如果真的出现异常,程序会直接 panic 终止,以避免进一步的问题。( 有意思,不知道工程特性如何。好处是可以尽早的发现bug地点 )
Go 支持参数可变函数。
defer
很特别,可以延迟调用函数,有点类似 Python 的上下文管理。但是可能有更多的使用场景。
panic
以后,defer 的函数仍然会执行!
panic 之后一般程序就会放弃执行,但是可以通过 recover 恢复执行。
组合和封装
绑定类型和函数
Go 的面向对象功能主要是通过 Method 实现封装和组合。我们可以为结构体类型指定相应的方法。所以在 Go 中并不强制绑定类型和方法:
1 | p := Point{1, 2} |
按照如下语法定义方法:
1 | type Point struct { |
应该注意的是,如果一个对象的方法是指针传入,那么按照传统,所有的其他方法都应该是指针传入,即使某些方法并不需要指针。
组合类型
组合类型主要是通过重复使用struct。
1 | // 可一个 unnamed strcut 使用 method |
封装
Go 通过首字母大小写区分是否 export 该变量或者函数。大写首字母会被export,小写则被封装。
接口, Interface
Go 的接口与其他语言类型,但是是隐式满足的,即一个类型不需要实现全部接口。(这是一个好主意么?)
接口类型与之前提到的concrete类型不用,一个实类型会明确数据结构以及该类型支持的具体函数(方法)。换句话说,当我们看到一个实类型,我们明确的知道这个类型可以做什么。而 Interface 类型属于抽象类型,他们仅仅确定该类型应该支持的操作函数的签名,但是不知道他具体会做什么。
1 | type Reader interface { |
为了让函数接受任意类型,我们可以传入 interface{}
类型。编译器会负责检查结构是否满足。
1 | var any interface{} |
Go 的 interface 可以有两种不同的使用范式:subtype polymorphism 和 ad hoc polymorphism。
后续专门讨论。