From 88fa04922ebe44b184dbf4f62efc51849c59aa94 Mon Sep 17 00:00:00 2001 From: leisore Date: Sun, 12 Jul 2015 23:12:35 +0800 Subject: [PATCH] ch10.6.1 OK --- eBook/10.6.md | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/eBook/10.6.md b/eBook/10.6.md index f28dfd0..220f433 100644 --- a/eBook/10.6.md +++ b/eBook/10.6.md @@ -19,7 +19,155 @@ func (a *denseMatrix) Add(b Matrix) Matrix func (a *sparseMatrix) Add(b Matrix) Matrix ``` +alias类型不能有它原始类型上已经定义过的方法。 +定义方法的一般格式如下: + + func (recv receiver_type) methodName(parameter_list) (return_value_list) { ... } + +在方法名之前,func关键字之后的括号中指定receiver。 + +如果recv是receiver的实例,Method1是它的方法名,那么方法调用遵循传统的object.name选择器符号:**recv.Method1()** + +如果recv一个指针,Go会自动解引用。 + +如果方法不需要使用recv的值,可以用*_*替换它,比如: + + func (_ receiver_type) methodName(parameter_list) (return_value_list) { ... } + +recv就像是OO语言中的this或self,但是Go中并没有这两个关键字。随个人喜好,你可以使用this或self作为receiver的名字。下面是一个结构体上的简单方法的例子: + +Listing 10.10—method .go +```go +package main + +import "fmt" + +type TwoInts struct { + a int + b int +} + +func main() { + two1 := new(TwoInts) + two1.a = 12 + two1.b = 10 + + fmt.Printf("The sum is: %d\n", two1.AddThem()) + fmt.Printf("Add them to the param: %d\n", two1.AddToParam(20)) + + two2 := TwoInts{3, 4} + fmt.Printf("The sum is: %d\n", two2.AddThem()) +} + +func (tn *TwoInts) AddThem() int { + return tn.a + tn.b +} + +func (tn *TwoInts) AddToParam(param int) int { + return tn.a + tn.b + param +} +``` + +输出: + + The sum is: 22 + Add them to the param: 42 + The sum is: 7 + +下面是非结构体类型上方法的例子: + + Listing 10.11—method2.go: + + ```go + package main + +import "fmt" + +type IntVector []int + +func (v IntVector) Sum() (s int) { + for _, x := range v { + s += x + } + return +} + +func main() { + fmt.Println(IntVector{1, 2, 3}.Sum()) // 输出是6 +} + ``` + +** 练习 10.6: employee_salary.go + +定义结构体employee,它有一个salary字段,给这个结构体定义一个方法giveRaise来按照指定的百分比增加薪水。 + +** 练习 10.7: iteration_list.go + +下面这段代码有什么错? + +```go +package main + +import "container/list" + +func (p *list.List) Iter() { + // ... +} + +func main() { + lst := new(list.List) + for _= range list.Iter() { + } +} +``` + +类型和作用在它上面定义的方法必须在同一个包里定义,这就是为什么不能在int、float或类似这些的类型上定义方法。试图在int类型上定义方法会得到一个编译错误: + + cannot define new methods on non-local type int + +比如想在time.Time上定义如下方法: + +```go +func (t time.Time) first3Chars() string { + return time.LocalTime().String()[0:3] +} +``` + +类型在在其他的,或是非本地的包里定义,在它上面定义方法都会得到和上面同样的错误。 + +但是有一个绕点的方式:可以先定义该类型(比如int,float)的别名类型,然后再为别名类型定义方法。或者像下面这样将它作为匿名类型嵌入在一个新的结构体中。当然方法只在这个别名类型上有效。 + +Listing 10.12—method_on_time.go: + +```go +package main + +import ( + "fmt" + "time" +) + +type myTime struct { + time.Time //anonymous field +} + +func (t myTime) first3Chars() string { + return t.Time.String()[0:3] +} +func main() { + m := myTime{time.Now()} + // 调用匿名Time上的String方法 + fmt.Println("Full time now:", m.String()) + // 调用myTime.first3Chars + fmt.Println("First 3 chars:", m.first3Chars()) +} + +/* Output: +Full time now: Mon Oct 24 15:34:54 Romance Daylight Time 2011 +First 3 chars: Mon +*/ +``` ## 链接 - [目录](directory.md)