记录一下之前的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

总结:

  1. 定义一个接口,里面设计好需要的接口,可以有多个(Attack (), Attack()1 ..)

  2. 任何实现了这个接口的类,都可以赋值给这个接口,从而实现多态

  3. 多个类之间不需要有继承关系

  4. 如果interface中定义了多个接口,那么实际的类必须全部实现接口函数,才可以赋值

1586070335758