记录一下之前的Go学习笔记。
go语言支持类的操作,但是没有class关键字,使用struct来模拟类
1.封装-绑定方法
1package main
2
3import "fmt"
4
5//Person类,绑定方法:Eat,Run,Laugh, 成员
6//public,private
7/*
8class Person {
9public :
10 string name
11 int age
12
13public :
14 Eat() {
15 xxx
16 }
17}
18
19*/
20
21//任何type的类型,都可以绑定方法
22type MyInt1 int
23
24func (mi *MyInt1) printMyInt() {
25 fmt.Println("MyInt value is:", *mi)
26}
27
28type Person struct {
29 //成员属性:
30 name string
31 age int
32 gender string
33 score float64
34}
35/*
36Person:::Eat() {
37
38}
39*/
40
41//在类外面绑定方法
42func (this *Person) Eat() {
43 //fmt.Println("Person is eating")
44 //类的方法,可以使用自己的成员
45 //fmt.Println(this.name + " is eating!")
46 this.name = "Duke"
47}
48
49func (this Person) Eat2() {
50 fmt.Println("Person is eating")
51 //类的方法,可以使用自己的成员
52 this.name = "Duke"
53}
54
55func main() {
56 lily := Person{
57 name: "Lily",
58 age: 30,
59 gender: "女生",
60 score: 10,
61 }
62
63 lily1 := lily
64
65 fmt.Println("Eat,使用p *Person,修改name的值 ...")
66 fmt.Println("修改前lily:", lily) //lily
67 lily.Eat()
68 fmt.Println("修改后lily:", lily) //Duke
69
70 fmt.Println("Eat2,使用p Person,但是不是指针 ...")
71 fmt.Println("修改前lily:", lily1) //lily
72 lily1.Eat2()
73 fmt.Println("修改后lily:", lily1) //lily
74
75 var myint1 MyInt1 = 100
76 myint1.printMyInt()
77}
执行结果:
1Eat,使用p *Person,修改name的值 ...
2修改前lily: {Lily 30 女生 10}
3修改后lily: {Duke 30 女生 10}
4Eat2,使用p Person,但是不是指针 ...
5修改前lily: {Lily 30 女生 10}
6Person is eating
7修改后lily: {Lily 30 女生 10}
8MyInt value is: 100
9
10Process finished with the exit code 0
2. 类继承
1package main
2
3import "fmt"
4
5type Human struct {
6 //成员属性:
7 name string
8 age int
9 gender string
10}
11
12//在类外面绑定方法
13func (this *Human) Eat() {
14 fmt.Println("this is :", this.name)
15}
16
17//定义一个学生类,去嵌套一个Hum
18type Student1 struct {
19 hum Human //包含Human类型的变量, 此时是类的嵌套
20 score float64
21 school string
22}
23
24//定义一个老师,去继承Human
25type Teacher struct {
26 Human //直接写Huam类型,没有字段名字
27 subject string //学科
28}
29
30func main() {
31 s1 := Student1{
32 hum: Human{
33 name: "Lily",
34 age: 18,
35 gender: "女生",
36 },
37 school: "昌平一中",
38 }
39
40 fmt.Println("s1.name:", s1.hum.name)
41 fmt.Println("s1.school:", s1.school)
42
43 t1 := Teacher{}
44 t1.subject = "语文"
45 t1.name = "荣老师" //下面这几个字段都是继承自Human
46 t1.age = 35
47 t1.gender = "女生"
48
49 fmt.Println("t1 :", t1)
50 t1.Eat()
51
52 //继承的时候,虽然我们没有定义字段名字,但是会自动创建一个默认的同名字段
53 //这是为了在子类中依然可以操作父类,因为:子类父类可能出现同名的字段
54 fmt.Println("t1.Human.name:", t1.Human.name)
55}
执行结果:
1s1.name: Lily
2s1.school: 昌平一中
3t1 : {{荣老师 35 女生} 语文}
4this is : 荣老师
5t1.Human.name: 荣老师
6
7Process finished with the exit code 0
访问权限
1//在go语言中,权限都是通过首字母大小来控制
2//1. import ==》 如果包名不同,那么只有大写字母开头的才是public的
3//2. 对于类里面的成员、方法===》只有大写开头的才能在其他包中使用
3. interface(接口)
1package main
2
3import "fmt"
4
5//在C++中,实现接口的时候,使用纯虚函数代替接口
6//在go语言中,有专门的关键字 interface来代表接口
7//interface不仅仅是用于处理多态的,它可以接受任意的数据类型,有点类似void
8
9func main() {
10 //func Println(a ...interface{}) (n int, err error) {
11 fmt.Println("")
12
13 //var i,j,k int
14 //定义三个接口类型
15 var i, j, k interface{}
16 names := []string{"duke", "lily"}
17 i = names
18 fmt.Println("i代表切片数组:", i)
19
20 age := 20
21 j = age
22 fmt.Println("j代表数字:", j)
23
24 str := "hello"
25 k = str
26 fmt.Println("k代表字符串:", k)
27
28}
执行结果:
1i代表切片数组: [duke lily]
2j代表数字: 20
3k代表字符串: hello
4
5Process finished with the exit code 0
另外一个案例:
1package main
2
3import "fmt"
4
5//在C++中,实现接口的时候,使用纯虚函数代替接口
6//在go语言中,有专门的关键字 interface来代表接口
7//interface不仅仅是用于处理多态的,它可以接受任意的数据类型,有点类似void
8
9func main() {
10 //func Println(a ...interface{}) (n int, err error) {
11 fmt.Println("")
12
13 //var i,j,k int
14 //定义三个接口类型
15 var i, j, k interface{}
16 names := []string{"duke", "lily"}
17 i = names
18 fmt.Println("i代表切片数组:", i)
19
20 age := 20
21 j = age
22 fmt.Println("j代表数字:", j)
23
24 str := "hello"
25 k = str
26 fmt.Println("k代表字符串:", k)
27
28 //我们现在只知道k是interface,但是不能够明确知道它代表的数据的类型
29 kvalue, ok := k.(int) //<<<==== 做类型的二次确认
30 if !ok {
31 fmt.Println("k不是int")
32 } else {
33 fmt.Println("k是int, 值为:", kvalue)
34 }
35
36 //最常用的场景: 把interface当成一个函数的参数,(类似于print),使用switch来判断用户输入的不同类型
37 //根据不同类型,做相应逻辑处理
38
39 //创建一个具有三个接口类型的切片
40 array := make([]interface{}, 3)
41 array[0] = 1
42 array[1] = "Hello world"
43 array[2] = 3.14
44
45 for _, value := range array {
46 //可以获取当前接口的真正数据类型
47 switch v := value.(type) {
48 case int:
49 fmt.Printf("当前类型为int, 内容为:%d\n", v)
50 case string:
51 fmt.Printf("当前类型为string, 内容为: %s\n", v)
52 case bool:
53 fmt.Printf("当前类型为bool, 内容为: %v\n", v) //%v可以自动推到输出类型
54 default:
55 fmt.Println("不是合理的数据类型")
56 }
57 }
58}
执行结果:
1i代表切片数组: [duke lily]
2j代表数字: 20
3k代表字符串: hello
4k不是int
5当前类型为int, 内容为:1
6当前类型为string, 内容为: Hello world
7不是合理的数据类型
8
9Process finished with the exit code 0
4. 多态
C语言的多态需要父子继承关系
go语言的多态不需要继承,只要实现相同的接口即可
1package main
2
3import "fmt"
4
5//实现go多态,需要实现定义接口
6//人类的武器发起攻击,不同等级子弹效果不同
7
8//定义一个接口, 注意类型是interface
9type IAttack interface {
10 //接口函数可以有多个,但是只能有函数原型,不可以有实现
11 Attack()
12 //Attack1()
13}
14
15//低等级
16type HumanLowLevel struct {
17 name string
18 level int
19}
20
21func (a *HumanLowLevel) Attack() {
22 fmt.Println("我是:", a.name, ",等级为:", a.level, ", 造成1000点伤害")
23}
24
25//高等级
26type HumanHighLevel struct {
27 name string
28 level int
29}
30
31func (a *HumanHighLevel) Attack() {
32 fmt.Println("我是:", a.name, ",等级为:", a.level, ", 造成5000点伤害")
33}
34
35//定义一个多态的通用接口,传入不同的对象,调用同样的方法,实现不同的效果 ==》 多态
36func DoAttack(a IAttack) {
37 a.Attack()
38}
39
40func main() {
41 //var player interface{}
42 var player IAttack //定义一个包含Attack的接口变量
43
44 lowLevel := HumanLowLevel{
45 name: "David",
46 level: 1,
47 }
48
49 highLevel := HumanHighLevel{
50 name: "David",
51 level: 10,
52 }
53
54 lowLevel.Attack()
55 highLevel.Attack()
56
57 //对player赋值为lowLevel,接口需要使用指针类型来赋值
58 player = &lowLevel
59 player.Attack()
60
61 player = &highLevel
62 player.Attack()
63
64 fmt.Println("多态......")
65 DoAttack(&lowLevel)
66 DoAttack(&highLevel)
67}
执行结果:
1我是: David ,等级为: 1 , 造成1000点伤害
2我是: David ,等级为: 10 , 造成5000点伤害
3我是: David ,等级为: 1 , 造成1000点伤害
4我是: David ,等级为: 10 , 造成5000点伤害
5多态......
6我是: David ,等级为: 1 , 造成1000点伤害
7我是: David ,等级为: 10 , 造成5000点伤害
8
9Process finished with the exit code 0
总结:
-
定义一个接口,里面设计好需要的接口,可以有多个(Attack (), Attack()1 ..)
-
任何实现了这个接口的类,都可以赋值给这个接口,从而实现多态
-
多个类之间不需要有继承关系
-
如果interface中定义了多个接口,那么实际的类必须全部实现接口函数,才可以赋值