From 65aa4e36d208a56efd3dea78014713ae2ae8dc67 Mon Sep 17 00:00:00 2001 From: Oling Cat Date: Sat, 22 Sep 2012 16:00:26 +0800 Subject: [PATCH] Fixed something wrong. --- 2.2.md | 2 +- 2.3.md | 100 ++++++++++----------- 2.4.md | 178 ++++++++++++++++++------------------- 2.5.md | 272 ++++++++++++++++++++++++++++----------------------------- 4 files changed, 276 insertions(+), 276 deletions(-) diff --git a/2.2.md b/2.2.md index 5205dcb3..3cbe28b0 100644 --- a/2.2.md +++ b/2.2.md @@ -395,7 +395,7 @@ slice有一些简便的操作 // map有两个返回值,第二个返回值,如果不存在key,那么ok为false,如果存在ok为true csharpRating, ok := rating["C#"] if ok { - fmt.Println("C# is in the map and its rating is ", csharp_rating) + fmt.Println("C# is in the map and its rating is ", csharpRating) } else { fmt.Println("We have no rating associated with C# in the map") } diff --git a/2.3.md b/2.3.md index 8065f08a..df56bb8e 100644 --- a/2.3.md +++ b/2.3.md @@ -1,9 +1,9 @@ #2.3 流程和函数 这小节我们要介绍Go里面的流程控制以及函数操作 ##流程控制 -流程控制是最伟大的发明了,因为有了它,你可以通过很简单的描述来表达很复杂的事情 +流程控制在编程语言中是最伟大的发明了,因为有了它,你可以通过很简单的描述来表达很复杂的事情。 ###if -if语法也许是所有语言里面最常见的一种语法了,它的语法概括起来就是:`如果满足条件就做某事,否则做另一件事` +`if`也许是所有语言中最常见的了,它的语法概括起来就是:`如果满足条件就做某事,否则做另一件事` Go里面`if`条件语法中不需要括号,如下代码所示 @@ -15,7 +15,7 @@ Go里面`if`条件语法中不需要括号,如下代码所示 Go的`if`还有一个强大的地方就是条件里面允许声明一个变量,这个变量的作用域只能在该条件中,出了这个条件就不起作用了,如下所示 - // 计算获取值x,然后根据x返回的大小,判断是否大于10. + // 计算获取值x,然后根据x返回的大小,判断是否大于10。 if x := computedValue(); x > 10 { fmt.Println("x is greater than 10") } else { @@ -25,7 +25,7 @@ Go的`if`还有一个强大的地方就是条件里面允许声明一个变量 //这个地方如果这样调用就编译出错了,因为x是条件里面的变量 fmt.Println(x) -多个条件的时候如下所示 +多个条件的时候如下所示: if integer == 3 { fmt.Println("The integer is equal to 3") @@ -50,15 +50,15 @@ Go有`goto`语句——请明智地使用它。用`goto`跳转到一定是当前 标签名是大小写敏感的。 ###for -Go里面最强大的一个控制逻辑就是`for`,它即可以用来循环读取数据,又可以当作`while`来控制逻辑,还能迭代操作。它的语法如下 +Go里面最强大的一个控制逻辑就是`for`,它即可以用来循环读取数据,又可以当作`while`来控制逻辑,还能迭代操作。它的语法如下: for expression1; expression2; expression3 { - ... + //... } `expression1`、`expression2`和`expression3`都是表达式,其中`expression1`和`expression3`是变量声明或者函数调用返回值之类的,`expression2`是条件判断,`expression1`在循环开始之前调用,`expression3`在每轮循环结束之时调用。 -一个例子比上面讲那么多更有用,那么我们看看下面的例子吧 +一个例子比上面讲那么多更有用,那么我们看看下面的例子吧: package main import "fmt" @@ -70,9 +70,9 @@ Go里面最强大的一个控制逻辑就是`for`,它即可以用来循环读 } fmt.Println("sum is equal to ", sum) } - //输出:sum is equal to 45 + // 输出:sum is equal to 45 -有些时候有多个需要操作的赋值操作,由于Go里面没有`,`操作,那么可以使用平行赋值`i, j = i+1, j-1` +有些时候需要进行多个赋值操作,由于Go里面没有`,`操作,那么可以使用平行赋值`i, j = i+1, j-1` 有些时候如果我们忽略`expression1`和`expression3`: @@ -82,23 +82,23 @@ Go里面最强大的一个控制逻辑就是`for`,它即可以用来循环读 sum += sum } -其中`;`也可以省略,那么就变成如下的代码了,是不是似曾相识,对,这就是`while`的功能 +其中`;`也可以省略,那么就变成如下的代码了,是不是似曾相识?对,这就是`while`的功能。 sum := 1 for sum < 1000 { sum += sum } -在循环里面有两个关键操作`break`和`continue` ,`break`操作是跳出当前循环,`continue`是跳出本次循环,当嵌套过深的时候,`break`可以配合标签使用,即跳出标签所指定的循环,详细参考如下例子 +在循环里面有两个关键操作`break`和`continue` ,`break`操作是跳出当前循环,`continue`是跳过本次循环。当嵌套过深的时候,`break`可以配合标签使用,即跳转至标签所指定的位置,详细参考如下例子: for index := 10; index>0; index-- { if index == 5{ - break或者continue + break // 或者continue } fmt.Println(index) } - //break打印出来10、9、8、7、6 - //continue打印出来10、9、8、7、6、4、3、2、1 + // break打印出来10、9、8、7、6 + // continue打印出来10、9、8、7、6、4、3、2、1 `break`和`continue`还可以跟着标号,用来跳到多重循环中的外层循环 @@ -109,11 +109,11 @@ Go里面最强大的一个控制逻辑就是`for`,它即可以用来循环读 fmt.Println("map's val:",v) } -其中还可以使用`_`来扔掉不需要的返回值 +其中还可以使用`_`来丢弃不需要的返回值 ###switch -有些时候你需要写很多的`if/else`来实现一些逻辑处理,这个时候代码看上去就很丑很冗长,而且也不易于以后的维护,这个时候`switch`就能很好的解决这个问题,它的语法如下 +有些时候你需要写很多的`if-else`来实现一些逻辑处理,这个时候代码看上去就很丑很冗长,而且也不易于以后的维护,这个时候`switch`就能很好的解决这个问题。它的语法如下 switch sExpr { case expr1: @@ -126,7 +126,7 @@ Go里面最强大的一个控制逻辑就是`for`,它即可以用来循环读 other code } -`sExpr`和`expr1`、`expr2`、`expr3`的类型必须一致。Go的`switch`非常灵活。表达式不必是常量或整数,执行的过程从上至下,直到找到匹配项,而如果`switch`没有表达式,它会匹配`true`。 +`sExpr`和`expr1`、`expr2`、`expr3`的类型必须一致。Go的`switch`非常灵活,表达式不必是常量或整数,执行的过程从上至下,直到找到匹配项;而如果`switch`没有表达式,它会匹配`true`。 i := 10 switch i { @@ -144,23 +144,23 @@ Go里面最强大的一个控制逻辑就是`for`,它即可以用来循环读 integer := 6 switch integer { - case 4: - fmt.Println("The integer was <= 4") - fallthrough - case 5: - fmt.Println("The integer was <= 5") - fallthrough - case 6: - fmt.Println("The integer was <= 6") - fallthrough - case 7: - fmt.Println("The integer was <= 7") - fallthrough - case 8: - fmt.Println("The integer was <= 8") - fallthrough - default: - fmt.Println("default case") + case 4: + fmt.Println("The integer was <= 4") + fallthrough + case 5: + fmt.Println("The integer was <= 5") + fallthrough + case 6: + fmt.Println("The integer was <= 6") + fallthrough + case 7: + fmt.Println("The integer was <= 7") + fallthrough + case 8: + fmt.Println("The integer was <= 8") + fallthrough + default: + fmt.Println("default case") } 上面的程序将输出 @@ -172,7 +172,7 @@ Go里面最强大的一个控制逻辑就是`for`,它即可以用来循环读 ##函数 -函数是Go里面的核心设计,它通过关键字`func`来声明,它的格式如下 +函数是Go里面的核心设计,它通过关键字`func`来声明,它的格式如下: func funcName(input1 type1, input2 type2) (output1 type1, output2 type2) { //这里是处理逻辑代码 @@ -194,7 +194,7 @@ Go里面最强大的一个控制逻辑就是`for`,它即可以用来循环读 package main import "fmt" - //返回a、b中最大值. + // 返回a、b中最大值. func max(a, b int) int { if a > b { return a @@ -212,7 +212,7 @@ Go里面最强大的一个控制逻辑就是`for`,它即可以用来循环读 fmt.Printf("max(%d, %d) = %d\n", x, y, max_xy) fmt.Printf("max(%d, %d) = %d\n", x, z, max_xz) - fmt.Printf("max(%d, %d) = %d\n", y, z, max(y,z)) //just call it here + fmt.Printf("max(%d, %d) = %d\n", y, z, max(y,z)) // 也可在这直接调用它 } 上面这个里面我们可以看到`max`函数有两个参数,它们的类型都是`int`,那么第一个变量的类型可以省略,默认为离它最近的类型,同理多于2个同类型的变量或者返回值。同时我们注意到它的返回值就是一个类型,这个就是省略写法。 @@ -240,7 +240,7 @@ Go语言和C相比,更先进的地方,其中一点就是能够返回多个 fmt.Printf("%d * %d = %d\n", x, y, xTIMESy) } -上面的例子我们可以看到直接返回了两个参数,当然我们也可以命名返回参数的变量,这个例子里面只是用了两个类型,我们也可以改成如下这样的定义,然后返回的时候不用带上变量名,因为直接在函数里面初始化了。但是当你的函数如果是导出的(首字母大写),官方建议,不要命名返回值名称,因为这样会造成生成的文档不易读。 +上面的例子我们可以看到直接返回了两个参数,当然我们也可以命名返回参数的变量,这个例子里面只是用了两个类型,我们也可以改成如下这样的定义,然后返回的时候不用带上变量名,因为直接在函数里面初始化了。但如果你的函数是导出的(首字母大写),官方建议,不要命名返回值,因为这样会造成生成的文档不易读。 func SumAndProduct(A, B int) (add int, Multiplied int) { add = A+B @@ -275,17 +275,17 @@ Go函数支持变参。接受变参的函数是有着不定数量的参数的。 func main() { x := 3 - fmt.Println("x = ", x) // 应该输出 "x = 3" + fmt.Println("x = ", x) // 应该输出 "x = 3" - x1 := add1(x) //调用add1(x) + x1 := add1(x) //调用add1(x) fmt.Println("x+1 = ", x1) // 应该输出"x+1 = 4" - fmt.Println("x = ", x) // 应该输出"x = 3" + fmt.Println("x = ", x) // 应该输出"x = 3" } 看到了吗?虽然我们调用了`add1`函数,并且在`add1`中执行`a=a+1`操作,但是上面例子中`x`变量的值没有发生变化 -理由很简单:因为当我们调用`add1`的时候,`add1`接收的参数其实是`x`的copy,而不是`x`本身 +理由很简单:因为当我们调用`add1`的时候,`add1`接收的参数其实是`x`的copy,而不是`x`本身。 那你也许会问了,如果真的需要传这个`x`本身,该怎么办呢? @@ -303,12 +303,12 @@ Go函数支持变参。接受变参的函数是有着不定数量的参数的。 func main() { x := 3 - fmt.Println("x = ", x) // 应该输出 "x = 3" + fmt.Println("x = ", x) // 应该输出 "x = 3" - x1 := add1(&x) // 调用 add1(&x) 传x的地址 + x1 := add1(&x) // 调用 add1(&x) 传x的地址 fmt.Println("x+1 = ", x1) // 应该输出 "x+1 = 4" - fmt.Println("x = ", x) // 应该输出 "x = 4" + fmt.Println("x = ", x) // 应该输出 "x = 4" } 这样,我们就达到了修改`x`的目的。那么到底传指针有什么好处呢? @@ -368,7 +368,7 @@ Go里面有一个不错的设计,就是回调函数,有点类似面向对象 package main import "fmt" - type testInt func(int) bool //声明了一个函数类型 + type testInt func(int) bool // 声明了一个函数类型 func isOdd(integer int) bool { if integer%2 == 0 { @@ -384,8 +384,8 @@ Go里面有一个不错的设计,就是回调函数,有点类似面向对象 return false } - //声明的函数类型在这个地方当做了一个参数 - func filter(slice []int, f test_int) []int { + // 声明的函数类型在这个地方当做了一个参数 + func filter(slice []int, f testInt) []int { var result []int for _, value := range slice { if f(value) { @@ -398,9 +398,9 @@ Go里面有一个不错的设计,就是回调函数,有点类似面向对象 func main(){ slice := []int {1, 2, 3, 4, 5, 7} fmt.Println("slice = ", slice) - odd := filter(slice, isOdd) //函数当做值来传递了 + odd := filter(slice, isOdd) // 函数当做值来传递了 fmt.Println("Odd elements of slice are: ", odd) - even := filter(slice, isEven)//函数当做值来传递了 + even := filter(slice, isEven) // 函数当做值来传递了 fmt.Println("Even elements of slice are: ", even) } diff --git a/2.4.md b/2.4.md index 654ef074..0c6df151 100644 --- a/2.4.md +++ b/2.4.md @@ -6,23 +6,23 @@ Go语言中,也和C或者其他语言一样,我们可以声明新的类型 name string age int } -看到了吗?申明一个struct如此简单,上面的类型包含有两个字段 +看到了吗?声明一个struct如此简单,上面的类型包含有两个字段 - 一个string类型的字段name,用来保存用户名称这个属性 - 一个int类型的字段age,用来保存用户年龄这个属性 如何使用struct呢?请看下面的代码 type person struct { - name string - age int + name string + age int } - var P person // P现在就是person类型的变量了 + var P person // P现在就是person类型的变量了 - P.name = "Astaxie" //赋值"Astaxie"给P的name属性. - P.age = 25 //赋值"25"给变量P的age属性 - fmt.Printf("The person's name is %s", P.name) // 访问P的name属性. -除了上面这种P的申明使用之外,还有两种申明使用方式 + P.name = "Astaxie" // 赋值"Astaxie"给P的name属性. + P.age = 25 // 赋值"25"给变量P的age属性 + fmt.Printf("The person's name is %s", P.name) // 访问P的name属性. +除了上面这种P的声明使用之外,还有两种声明使用方式 - 1.按照顺序提供初始化值 @@ -37,45 +37,45 @@ Go语言中,也和C或者其他语言一样,我们可以声明新的类型 package main import "fmt" - //申明一个新的类型 + // 声明一个新的类型 type person struct { - name string - age int + name string + age int } // 比较两个人的年龄,返回年龄大的那个人,并且返回年龄差 // struct也是传值的 func Older(p1, p2 person) (person, int) { - if p1.age>p2.age { //比较p1和p2这两个人的年龄 - return p1, p1.age-p2.age - } - return p2, p2.age-p1.age + if p1.age>p2.age { // 比较p1和p2这两个人的年龄 + return p1, p1.age-p2.age + } + return p2, p2.age-p1.age } func main() { - var tom person + var tom person - //赋值初始化 - tom.name, tom.age = "Tom", 18 + // 赋值初始化 + tom.name, tom.age = "Tom", 18 - //两个字段都写清楚的初始化 - bob := person{age:25, name:"Bob"} + // 两个字段都写清楚的初始化 + bob := person{age:25, name:"Bob"} - //按照struct定义顺序初始化值 - paul := person{"Paul", 43} + // 按照struct定义顺序初始化值 + paul := person{"Paul", 43} - tb_Older, tb_diff := Older(tom, bob) - tp_Older, tp_diff := Older(tom, paul) - bp_Older, bp_diff := Older(bob, paul) + tb_Older, tb_diff := Older(tom, bob) + tp_Older, tp_diff := Older(tom, paul) + bp_Older, bp_diff := Older(bob, paul) - fmt.Printf("Of %s and %s, %s is older by %d years\n", - tom.name, bob.name, tb_Older.name, tb_diff) + fmt.Printf("Of %s and %s, %s is older by %d years\n", + tom.name, bob.name, tb_Older.name, tb_diff) - fmt.Printf("Of %s and %s, %s is older by %d years\n", - tom.name, paul.name, tp_Older.name, tp_diff) + fmt.Printf("Of %s and %s, %s is older by %d years\n", + tom.name, paul.name, tp_Older.name, tp_diff) - fmt.Printf("Of %s and %s, %s is older by %d years\n", - bob.name, paul.name, bp_Older.name, bp_diff) + fmt.Printf("Of %s and %s, %s is older by %d years\n", + bob.name, paul.name, bp_Older.name, bp_diff) } ###struct的匿名字段 @@ -89,37 +89,37 @@ Go语言中,也和C或者其他语言一样,我们可以声明新的类型 import "fmt" type Human struct { - name string - age int - weight int + name string + age int + weight int } type Student struct { - Human //匿名字段,那么默认Student就包含了Human的所有字段 - speciality string + Human // 匿名字段,那么默认Student就包含了Human的所有字段 + speciality string } func main() { - //我们初始化一个学生 - mark := Student{Human{"Mark", 25, 120}, "Computer Science"} + // 我们初始化一个学生 + mark := Student{Human{"Mark", 25, 120}, "Computer Science"} - //我们访问相应的字段 - fmt.Println("His name is ", mark.name) - fmt.Println("His age is ", mark.age) - fmt.Println("His weight is ", mark.weight) - fmt.Println("His speciality is ", mark.speciality) - //修改对应的备注信息 - mark.speciality = "AI" - fmt.Println("Mark changed his speciality") - fmt.Println("His speciality is ", mark.speciality) - //修改他的年龄信息 - fmt.Println("Mark become old") - mark.age = 46 - fmt.Println("His age is", mark.age) - //修改他的体重信息 - fmt.Println("Mark is not an athlet anymore") - mark.weight += 60 - fmt.Println("His weight is", mark.weight) + // 我们访问相应的字段 + fmt.Println("His name is ", mark.name) + fmt.Println("His age is ", mark.age) + fmt.Println("His weight is ", mark.weight) + fmt.Println("His speciality is ", mark.speciality) + // 修改对应的备注信息 + mark.speciality = "AI" + fmt.Println("Mark changed his speciality") + fmt.Println("His speciality is ", mark.speciality) + // 修改他的年龄信息 + fmt.Println("Mark become old") + mark.age = 46 + fmt.Println("His age is", mark.age) + // 修改他的体重信息 + fmt.Println("Mark is not an athlet anymore") + mark.weight += 60 + fmt.Println("His weight is", mark.weight) } 我们看到Student访问属性age和name的时候,就像访问自己所有用的字段一样,对,匿名字段就是这样,能够实现字段的继承。是不是很酷啊?还有比这个更酷的呢,那就是student还能访问Human这个字段作为字段名。请看下面的代码,是不是更酷了。 @@ -135,38 +135,38 @@ Go语言中,也和C或者其他语言一样,我们可以声明新的类型 type Skills []string type Human struct { - name string - age int - weight int + name string + age int + weight int } type Student struct { - Human //匿名字段,struct - Skills //匿名字段,自定义的类型string slice - int //内置类型作为匿名字段 - speciality string + Human // 匿名字段,struct + Skills // 匿名字段,自定义的类型string slice + int // 内置类型作为匿名字段 + speciality string } func main() { - //初始化学生Jane - jane := Student{Human:Human{"Jane", 35, 100}, speciality:"Biology"} - //现在我们来访问相应的字段 - fmt.Println("Her name is ", jane.name) - fmt.Println("Her age is ", jane.age) - fmt.Println("Her weight is ", jane.weight) - fmt.Println("Her speciality is ", jane.speciality) - //我们来修改他的skill技能字段 - jane.Skills = []string{"anatomy"} - fmt.Println("Her skills are ", jane.Skills) - fmt.Println("She acquired two new ones ") - jane.Skills = append(jane.Skills, "physics", "golang") - fmt.Println("Her skills now are ", jane.Skills) - //修改匿名内置类型字段 - jane.int = 3 - fmt.Println("Her preferred number is", jane.int) + // 初始化学生Jane + jane := Student{Human:Human{"Jane", 35, 100}, speciality:"Biology"} + // 现在我们来访问相应的字段 + fmt.Println("Her name is ", jane.name) + fmt.Println("Her age is ", jane.age) + fmt.Println("Her weight is ", jane.weight) + fmt.Println("Her speciality is ", jane.speciality) + // 我们来修改他的skill技能字段 + jane.Skills = []string{"anatomy"} + fmt.Println("Her skills are ", jane.Skills) + fmt.Println("She acquired two new ones ") + jane.Skills = append(jane.Skills, "physics", "golang") + fmt.Println("Her skills now are ", jane.Skills) + // 修改匿名内置类型字段 + jane.int = 3 + fmt.Println("Her preferred number is", jane.int) } -从上面例子我们看出来struct不仅仅能够将struct作为匿名字段、自定义类型、内置类型都可以作为匿名字段,而且可以在相应的字段上面进行函数操作(如例子中的append)。 +从上面例子我们看出来struct不仅仅能够将struct作为匿名字段、自定义类型、内置类型都可以作为匿名字段,而且可以在相应的字段上面进行函数操作(如例子中的append)。 这里有一个问题:如果human里面有一个字段叫做phone,而student也有一个字段叫做phone,那么该怎么办呢? @@ -178,22 +178,22 @@ Go里面很简单的解决了这个问题,最外层的优先访问,也就是 import "fmt" type Human struct { - name string - age int - phone string //Human类型拥有的字段 + name string + age int + phone string // Human类型拥有的字段 } type Employee struct { - Human //匿名字段Human - speciality string - phone string //雇员的phone字段 + Human // 匿名字段Human + speciality string + phone string // 雇员的phone字段 } func main() { - Bob := Employee{Human{"Bob", 34, "777-444-XXXX"}, "Designer", "333-222"} - fmt.Println("Bob's work phone is:", Bob.phone) - //如果我们要访问Human的phone字段 - fmt.Println("Bob's personal phone is:", Bob.Human.phone) + Bob := Employee{Human{"Bob", 34, "777-444-XXXX"}, "Designer", "333-222"} + fmt.Println("Bob's work phone is:", Bob.phone) + // 如果我们要访问Human的phone字段 + fmt.Println("Bob's personal phone is:", Bob.Human.phone) } diff --git a/2.5.md b/2.5.md index f67dc29b..2a15673d 100644 --- a/2.5.md +++ b/2.5.md @@ -6,23 +6,23 @@ package main import "fmt" - + type Rectangle struct { - width, height float64 - } - - func area(r Rectangle) float64 { - return r.width*r.height - } - - func main() { - r1 := Rectangle{12, 2} - r2 := Rectangle{9, 4} - fmt.Println("Area of r1 is: ", area(r1)) - fmt.Println("Area of r2 is: ", area(r2)) + width, height float64 } -这个代码是可以计算出来长方形的面积,但是area不是作为Rectangle的一个方法(类似面向对象里面的方法)实现的, 而是Rectangle的对象(r1,r2)作为函数的一个参数传入,然后计算获取的。 + func area(r Rectangle) float64 { + return r.width*r.height + } + + func main() { + r1 := Rectangle{12, 2} + r2 := Rectangle{9, 4} + fmt.Println("Area of r1 is: ", area(r1)) + fmt.Println("Area of r2 is: ", area(r2)) + } + +这个代码是可以计算出来长方形的面积,但是area不是作为Rectangle的一个方法(类似面向对象里面的方法)实现的,而是Rectangle的对象(r1,r2)作为函数的一个参数传入,然后计算获取的。 这样实现有什么问题,当然没有问题咯,但是当你代码里面增加一个圆形、正方形、多边形等的时候,然后你又想计算他们的面积的时候怎么办啊?那就增加新的函数咯,但是函数名你就必须要跟着换了,你就要把函数名变成`area_rectangle, area_circle, area_triangle...` @@ -34,9 +34,9 @@ >“A method is a function with an implicit first argument, called a receiver.“ -method的语法如下: - - func (ReceiverType r) func_name (parameters) (results) +method的语法如下: + + func (ReceiverType r) funcName(parameters) (results) 下面我们用最开始的例子用method来实现: @@ -45,36 +45,36 @@ method的语法如下: "fmt" "math" ) - + type Rectangle struct { - width, height float64 + width, height float64 } - + type Circle struct { - radius float64 + radius float64 } - + func (r Rectangle) area() float64 { - return r.width*r.height + return r.width*r.height } - + func (c Circle) area() float64 { - return c.radius * c.radius * math.Pi + return c.radius * c.radius * math.Pi } - - + + func main() { - r1 := Rectangle{12, 2} - r2 := Rectangle{9, 4} - c1 := Circle{10} - c2 := Circle{25} - - fmt.Println("Area of r1 is: ", r1.area()) - fmt.Println("Area of r2 is: ", r2.area()) - fmt.Println("Area of c1 is: ", c1.area()) - fmt.Println("Area of c2 is: ", c2.area()) + r1 := Rectangle{12, 2} + r2 := Rectangle{9, 4} + c1 := Circle{10} + c2 := Circle{25} + + fmt.Println("Area of r1 is: ", r1.area()) + fmt.Println("Area of r2 is: ", r2.area()) + fmt.Println("Area of c1 is: ", c1.area()) + fmt.Println("Area of c2 is: ", c2.area()) } - + 在使用method的时候重要注意几点 - 虽然method的名字一模一样,但是如果接收者不一样,那么method就不一样 @@ -83,8 +83,8 @@ method的语法如下: 那是不是method只能作用在struct上面呢?当然不是咯,他可以定义在任何你自定义的类型、内置类型、struct等各种类型上面。这里你是不是有点迷糊了,什么叫自定义类型,自定义类型不就是struct嘛,不是这样的哦,struct只是自定义类型里面一种比较特殊的类型而已,还有其他自定义类型申明,可以通过如下这样的申明来实现。 - type type_name type_literal - + type typeName typeLiteral + 请看下面这个申明自定义类型的代码 type ages int @@ -94,12 +94,12 @@ method的语法如下: type months map[string]int m := months { - "January":31, - "February":28, - ... - "December":31, - } - + "January":31, + "February":28, + ... + "December":31, + } + 看到了吗?简单的很吧,这样你就可以在自己的代码里面定义有意义的类型了,实际上只是一个定义了一个别名,有点类似于c中的typedef,例如上面ages替代了int 好了,让我们回到`method` @@ -110,75 +110,75 @@ method的语法如下: import "fmt" const( - WHITE = iota - BLACK - BLUE - RED - YELLOW + WHITE = iota + BLACK + BLUE + RED + YELLOW ) type Color byte - + type Box struct { - width, height, depth float64 - color Color + width, height, depth float64 + color Color } type BoxList []Box //a slice of boxes func (b Box) Volume() float64 { - return b.width * b.height * b.depth + return b.width * b.height * b.depth } - + func (b *Box) SetColor(c Color) { - b.color = c + b.color = c } - + func (bl BoxList) BiggestsColor() Color { - v := 0.00 - k := Color(WHITE) - for _, b := range bl { - if b.Volume() > v { - v = b.Volume() - k = b.color - } - } - return k + v := 0.00 + k := Color(WHITE) + for _, b := range bl { + if b.Volume() > v { + v = b.Volume() + k = b.color + } + } + return k } - + func (bl BoxList) PaintItBlack() { - for i, _ := range bl { - bl[i].SetColor(BLACK) - } + for i, _ := range bl { + bl[i].SetColor(BLACK) + } } - + func (c Color) String() string { - strings := []string {"WHITE", "BLACK", "BLUE", "RED", "YELLOW"} - return strings[c] + strings := []string {"WHITE", "BLACK", "BLUE", "RED", "YELLOW"} + return strings[c] } - + func main() { - boxes := BoxList { - Box{4, 4, 4, RED}, - Box{10, 10, 1, YELLOW}, - Box{1, 1, 20, BLACK}, - Box{10, 10, 1, BLUE}, - Box{10, 30, 1, WHITE}, - Box{20, 20, 20, YELLOW}, - } - - fmt.Printf("We have %d boxes in our set\n", len(boxes)) - fmt.Println("The volume of the first one is", boxes[0].Volume(), "cm³") - fmt.Println("The color of the last one is",boxes[len(boxes)-1].color.String()) - fmt.Println("The biggest one is", boxes.BiggestsColor().String()) - - fmt.Println("Let's paint them all black") - boxes.PaintItBlack() - fmt.Println("The color of the second one is", boxes[1].color.String()) - - fmt.Println("Obviously, now, the biggest one is", boxes.BiggestsColor().String()) + boxes := BoxList { + Box{4, 4, 4, RED}, + Box{10, 10, 1, YELLOW}, + Box{1, 1, 20, BLACK}, + Box{10, 10, 1, BLUE}, + Box{10, 30, 1, WHITE}, + Box{20, 20, 20, YELLOW}, + } + + fmt.Printf("We have %d boxes in our set\n", len(boxes)) + fmt.Println("The volume of the first one is", boxes[0].Volume(), "cm³") + fmt.Println("The color of the last one is",boxes[len(boxes)-1].color.String()) + fmt.Println("The biggest one is", boxes.BiggestsColor().String()) + + fmt.Println("Let's paint them all black") + boxes.PaintItBlack() + fmt.Println("The color of the second one is", boxes[1].color.String()) + + fmt.Println("Obviously, now, the biggest one is", boxes.BiggestsColor().String()) } - + 上面这个例子我们通过const定义了一些常量,然后定义了一些自定义类型 - Color作为byte的别名 @@ -223,34 +223,34 @@ method的语法如下: package main import "fmt" - + type Human struct { - name string - age int - phone string + name string + age int + phone string } - + type Student struct { - Human //匿名字段 - school string + Human //匿名字段 + school string } - + type Employee struct { - Human //匿名字段 - company string + Human //匿名字段 + company string } - + //在human上面定义了一个method func (h *Human) SayHi() { - fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone) + fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone) } - + func main() { - mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"} - sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"} - - mark.SayHi() - sam.SayHi() + mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"} + sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"} + + mark.SayHi() + sam.SayHi() } ###method重载 @@ -258,49 +258,49 @@ method的语法如下: package main import "fmt" - + type Human struct { - name string - age int - phone string + name string + age int + phone string } - + type Student struct { - Human //匿名字段 - school string + Human //匿名字段 + school string } - + type Employee struct { - Human //匿名字段 - company string + Human //匿名字段 + company string } - + //Human定义method func (h *Human) SayHi() { - fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone) + fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone) } - + //Employee的method重载Human的method 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) //Yes you can split into 2 lines here. + fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name, + e.company, e.phone) //Yes you can split into 2 lines here. } - + func main() { - mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"} - sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"} - - mark.SayHi() - sam.SayHi() + mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"} + sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"} + + mark.SayHi() + sam.SayHi() } - + 上面的代码设计的是如此的美妙,让人不自觉的为Go的设计惊叹! -通过这些内容,我们可以设计出基本的面向对象的程序了,但是Go里面的面向对象是如此的简单,没有任何的私有、共有关键字,通过大小写来实现(大写开头的为共有,小写开头的为私有),方法也同样适用这个原则。 +通过这些内容,我们可以设计出基本的面向对象的程序了,但是Go里面的面向对象是如此的简单,没有任何的私有、共有关键字,通过大小写来实现(大写开头的为共有,小写开头的为私有),方法也同样适用这个原则。 ## links * [目录]() * 上一章: [struct类型](<2.4.md>) * 下一节: [interface](<2.6.md>) -## LastModified +## LastModified * $Id$