From 61190a8a674d64481c47e38b897456e1514a746a Mon Sep 17 00:00:00 2001 From: xiemengjun Date: Wed, 29 Aug 2012 23:55:43 +0800 Subject: [PATCH] =?UTF-8?q?struct=E5=86=99=E5=AE=8C=E4=BA=86=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E4=BB=8B=E7=BB=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2.3.md | 2 +- 2.4.md | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 161 insertions(+), 2 deletions(-) diff --git a/2.3.md b/2.3.md index e4ef4564..9d4854f3 100644 --- a/2.3.md +++ b/2.3.md @@ -163,7 +163,7 @@ sExpr和expr1、expr2、expr3的类型必须一致。Go的switch非常灵活。 fmt.Println("default case") } -上面的程序讲输出 +上面的程序将输出 The integer was <= 6 The integer was <= 7 diff --git a/2.4.md b/2.4.md index 8469b96f..28557d2b 100644 --- a/2.4.md +++ b/2.4.md @@ -21,7 +21,7 @@ Go语言中,也和C或者其他语言中一样,我们可以声明新的类 P.name = "Astaxie" //赋值"Astaxie"给P的name属性. P.age = 25 //赋值"25"给变量P的age属性 - fmt.Println("The person's name is %s", P.name) // 访问P的name属性. + fmt.Printf("The person's name is %s", P.name) // 访问P的name属性. 除了上面这种P的申明使用之外,还有两种申明使用方式 - 1.按照顺序提供初始化值 @@ -32,10 +32,169 @@ Go语言中,也和C或者其他语言中一样,我们可以声明新的类 P := person{age:24, name:"Tom"} +下面我们看一个完整的使用strcut的例子 + package main + import "fmt" + //申明一个新的类型 + type person struct { + name string + age int + } + // 比较两个人的年龄,返回年龄大的那个人,并且返回年龄差 + //strcut也是传值的 + 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 + } + func main() { + var tom person + + //赋值初始化 + tom.name, tom.age = "Tom", 18 + + //两个字段都写清楚的初始化 + bob := person{age:25, name:"Bob"} + + //按照strcut定义顺序初始化值 + 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) + + 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", + bob.name, paul.name, bp_Older.name, bp_diff) + } + +###strcut的匿名字段 +我们上面介绍了如何定义一个strcut,定义字段的时候我们都是一个name,然后对应的一个type,实际上Go里面支持只写一个type,不用写name,也就是匿名字段。 + +当匿名字段是一个strcut的时候,那么默认这个strcut下面所有的字段被加入进了当前定义的这个strcut。 + +让我们来看一个例子,让上面说的这些更具体化 + + package main + import "fmt" + + type Human struct { + name string + age int + weight int + } + + type Student struct { + Human //匿名字段,那么默认Student就包含了Human的所有字段 + speciality string + } + + func main() { + //我们初始化一个学生 + 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) + } + +我们看到Student访问属性age和name的时候,就像访问自己所有用的字段一样,对,匿名字段就是这样,能够实现字段的继承。是不是很酷啊?还有比这个更酷的呢,那就是student还能访问Human这个字段作为字段名。请看下面的代码,是不是更酷了。 + + mark.Human = Human{"Marcus", 55, 220} + mark.Human.age -= 1 + +通过匿名访问和修改字段相当的有用,但是不仅仅是strcut字段哦,所有的内置类型和自定义类型都是可以作为匿名字段的。请看下面的例子 + + package main + import "fmt" + + type Skills []string + + type Human struct { + name string + age int + weight int + } + + type Student struct { + 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) + } + +从上面例子我们看出来strcut不仅仅能够strcut作为匿名字段、自定义类型、内置类型都可以作为匿名字段,而且可以在相应的字段上面进行函数操作(如例子中的append)。 + +这里有一个问题:如果human里面有一个字段叫做phone,而student也有一个字段叫做phone,那么该怎么办呢? + +Go里面很简单的解决了这个问题,最外层的优先访问,也就是当你通过`student.phone`访问的时候,是访问student里面的字段,而不是human里面的字段。 + +这样就允许我们去重载通过匿名字段继承的一些字段,当然如果我们想访问重载后对应匿名类型里面的字段,可以通过匿名字段名来访问。请看下面的例子 + + package main + import "fmt" + + type Human struct { + name string + age int + phone string //Human类型拥有的字段 + } + + type Employee struct { + 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) + } ##interface