Remove 02.6.md spaces

This commit is contained in:
vCaesar
2017-06-10 11:41:44 +08:00
parent 594fd4fdeb
commit 3cb9ed7598

View File

@@ -16,73 +16,73 @@ Go语言里面设计最精妙的应该算interface它让面向对象内容
interface类型定义了一组方法如果某个对象实现了某个接口的所有方法则此对象就实现了此接口。详细的语法参考下面这个例子
```Go
type Human struct {
type Human struct {
name string
age int
phone string
}
}
type Student struct {
type Student struct {
Human //匿名字段Human
school string
loan float32
}
}
type Employee struct {
type Employee struct {
Human //匿名字段Human
company string
money float32
}
}
//Human对象实现Sayhi方法
func (h *Human) SayHi() {
//Human对象实现Sayhi方法
func (h *Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
}
// Human对象实现Sing方法
func (h *Human) Sing(lyrics string) {
// Human对象实现Sing方法
func (h *Human) Sing(lyrics string) {
fmt.Println("La la, la la la, la la la la la...", lyrics)
}
}
//Human对象实现Guzzle方法
func (h *Human) Guzzle(beerStein string) {
//Human对象实现Guzzle方法
func (h *Human) Guzzle(beerStein string) {
fmt.Println("Guzzle Guzzle Guzzle...", beerStein)
}
}
// Employee重载Human的Sayhi方法
func (e *Employee) SayHi() {
// Employee重载Human的Sayhi方法
func (e *Employee) SayHi() {
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
e.company, e.phone) //此句可以分成多行
}
}
//Student实现BorrowMoney方法
func (s *Student) BorrowMoney(amount float32) {
//Student实现BorrowMoney方法
func (s *Student) BorrowMoney(amount float32) {
s.loan += amount // (again and again and...)
}
}
//Employee实现SpendSalary方法
func (e *Employee) SpendSalary(amount float32) {
//Employee实现SpendSalary方法
func (e *Employee) SpendSalary(amount float32) {
e.money -= amount // More vodka please!!! Get me through the day!
}
}
// 定义interface
type Men interface {
// 定义interface
type Men interface {
SayHi()
Sing(lyrics string)
Guzzle(beerStein string)
}
}
type YoungChap interface {
type YoungChap interface {
SayHi()
Sing(song string)
BorrowMoney(amount float32)
}
}
type ElderlyGent interface {
type ElderlyGent interface {
SayHi()
Sing(song string)
SpendSalary(amount float32)
}
}
```
通过上面的代码我们可以知道interface可以被任意的对象实现。我们看到上面的Men interface被Human、Student和Employee实现。同理一个对象可以实现任意多个interface例如上面的Student实现了Men和YoungChap两个interface。
@@ -96,52 +96,52 @@ interface类型定义了一组方法如果某个对象实现了某个接口
让我们来看一下下面这个例子:
```Go
package main
package main
import "fmt"
import "fmt"
type Human struct {
type Human struct {
name string
age int
phone string
}
}
type Student struct {
type Student struct {
Human //匿名字段
school string
loan float32
}
}
type Employee struct {
type Employee struct {
Human //匿名字段
company string
money float32
}
}
//Human实现SayHi方法
func (h Human) SayHi() {
//Human实现SayHi方法
func (h Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
}
//Human实现Sing方法
func (h Human) Sing(lyrics string) {
//Human实现Sing方法
func (h Human) Sing(lyrics string) {
fmt.Println("La la la la...", lyrics)
}
}
//Employee重载Human的SayHi方法
func (e Employee) SayHi() {
//Employee重载Human的SayHi方法
func (e Employee) SayHi() {
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
e.company, e.phone)
}
// Interface Men被Human,Student和Employee实现
// 因为这三个类型都实现了这两个方法
type Men interface {
// Interface Men被Human,Student和Employee实现
// 因为这三个类型都实现了这两个方法
type Men interface {
SayHi()
Sing(lyrics string)
}
}
func main() {
func main() {
mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.00}
paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100}
sam := Employee{Human{"Sam", 36, "444-222-XXX"}, "Golang Inc.", 1000}
@@ -171,7 +171,7 @@ interface类型定义了一组方法如果某个对象实现了某个接口
for _, value := range x{
value.SayHi()
}
}
}
```
通过上面的代码你会发现interface就是一组抽象方法的集合它必须由其他非interface类型实现而不能自我实现 Go通过interface实现了duck-typing:即"当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子"。
@@ -179,13 +179,13 @@ interface类型定义了一组方法如果某个对象实现了某个接口
空interface(interface{})不包含任何的method正因为如此所有的类型都实现了空interface。空interface对于描述起不到任何的作用(因为它不包含任何的method但是空interface在我们需要存储任意类型的数值的时候相当有用因为它可以存储任意类型的数值。它有点类似于C语言的void*类型。
```Go
// 定义a为空接口
var a interface{}
var i int = 5
s := "Hello world"
// a可以存储任意类型的数值
a = i
a = s
// 定义a为空接口
var a interface{}
var i int = 5
s := "Hello world"
// a可以存储任意类型的数值
a = i
a = s
```
一个函数把interface{}作为参数那么他可以接受任意类型的值作为参数如果一个函数返回interface{},那么也就可以返回任意类型的值。是不是很有用啊!
### interface函数参数
@@ -194,41 +194,41 @@ interface的变量可以持有任意实现该interface类型的对象这给
举个例子fmt.Println是我们常用的一个函数但是你是否注意到它可以接受任意类型的数据。打开fmt的源码文件你会看到这样一个定义:
```Go
type Stringer interface {
type Stringer interface {
String() string
}
}
```
也就是说任何实现了String方法的类型都能作为参数被fmt.Println调用,让我们来试一试
```Go
package main
import (
package main
import (
"fmt"
"strconv"
)
)
type Human struct {
type Human struct {
name string
age int
phone string
}
}
// 通过这个方法 Human 实现了 fmt.Stringer
func (h Human) String() string {
// 通过这个方法 Human 实现了 fmt.Stringer
func (h Human) String() string {
return "❰"+h.name+" - "+strconv.Itoa(h.age)+" years - ✆ " +h.phone+"❱"
}
}
func main() {
func main() {
Bob := Human{"Bob", 39, "000-7777-XXX"}
fmt.Println("This Human is : ", Bob)
}
}
```
现在我们再回顾一下前面的Box示例你会发现Color结构也定义了一个methodString。其实这也是实现了fmt.Stringer这个interface即如果需要某个类型能被fmt包以特殊的格式输出你就必须实现Stringer这个接口。如果没有实现这个接口fmt将以默认的方式输出。
```Go
//实现同样的功能
fmt.Println("The biggest one is", boxes.BiggestsColor().String())
fmt.Println("The biggest one is", boxes.BiggestsColor())
//实现同样的功能
fmt.Println("The biggest one is", boxes.BiggestsColor().String())
fmt.Println("The biggest one is", boxes.BiggestsColor())
```
实现了error接口的对象即实现了Error() string的对象使用fmt输出时会调用Error()方法因此不必再定义String()方法了。
### interface变量存储的类型
@@ -339,16 +339,16 @@ Go里面真正吸引人的是它内置的逻辑语法就像我们在学习Str
我们可以看到源码包container/heap里面有这样的一个定义
```Go
type Interface interface {
type Interface interface {
sort.Interface //嵌入字段sort.Interface
Push(x interface{}) //a Push method to push elements into the heap
Pop() interface{} //a Pop elements that pops elements from the heap
}
}
```
我们看到sort.Interface其实就是嵌入字段把sort.Interface的所有method给隐式的包含进来了。也就是下面三个方法
```Go
type Interface interface {
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less returns whether the element with index i should sort
@@ -356,16 +356,16 @@ Go里面真正吸引人的是它内置的逻辑语法就像我们在学习Str
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}
}
```
另一个例子就是io包下面的 io.ReadWriter 它包含了io包下面的Reader和Writer两个interface
```Go
// io.ReadWriter
type ReadWriter interface {
// io.ReadWriter
type ReadWriter interface {
Reader
Writer
}
}
```
### 反射
Go语言实现了反射所谓反射就是能检查程序在运行时的状态。我们一般用到的包是reflect包。如何运用reflect包官方的这篇文章详细的讲解了reflect包的实现原理[laws of reflection](http://golang.org/doc/articles/laws_of_reflection.html)
@@ -373,38 +373,38 @@ Go语言实现了反射所谓反射就是能检查程序在运行时的状态
使用reflect一般分成三步下面简要的讲解一下要去反射是一个类型的值(这些值都实现了空interface)首先需要把它转化成reflect对象(reflect.Type或者reflect.Value根据不同的情况调用不同的函数)。这两种获取方式如下:
```Go
t := reflect.TypeOf(i) //得到类型的元数据,通过t我们能获取类型定义里面的所有元素
v := reflect.ValueOf(i) //得到实际的值通过v我们获取存储在里面的值还可以去改变值
t := reflect.TypeOf(i) //得到类型的元数据,通过t我们能获取类型定义里面的所有元素
v := reflect.ValueOf(i) //得到实际的值通过v我们获取存储在里面的值还可以去改变值
```
转化为reflect对象之后我们就可以进行一些操作了也就是将reflect对象转化成相应的值例如
```Go
tag := t.Elem().Field(0).Tag //获取定义在struct里面的标签
name := v.Elem().Field(0).String() //获取存储在第一个字段里面的值
tag := t.Elem().Field(0).Tag //获取定义在struct里面的标签
name := v.Elem().Field(0).String() //获取存储在第一个字段里面的值
```
获取反射值能返回相应的类型和数值
```Go
var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("type:", v.Type())
fmt.Println("kind is float64:", v.Kind() == reflect.Float64)
fmt.Println("value:", v.Float())
var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("type:", v.Type())
fmt.Println("kind is float64:", v.Kind() == reflect.Float64)
fmt.Println("value:", v.Float())
```
最后,反射的话,那么反射的字段必须是可修改的,我们前面学习过传值和传引用,这个里面也是一样的道理。反射的字段必须是可读写的意思是,如果下面这样写,那么会发生错误
```Go
var x float64 = 3.4
v := reflect.ValueOf(x)
v.SetFloat(7.1)
var x float64 = 3.4
v := reflect.ValueOf(x)
v.SetFloat(7.1)
```
如果要修改相应的值,必须这样写
```Go
var x float64 = 3.4
p := reflect.ValueOf(&x)
v := p.Elem()
v.SetFloat(7.1)
var x float64 = 3.4
p := reflect.ValueOf(&x)
v := p.Elem()
v.SetFloat(7.1)
```
上面只是对反射的简单介绍,更深入的理解还需要自己在编程中不断的实践。