Golang学习 - 方法
hanpy

Go 没有沿袭传统面向对象编程中的诸多概念,也没有提供类( class ),但是它提供了结构体( struc),方法( method )可以在结构体上添加。与类相似,结构体提供了捆绑数据和方法的行为。

结构体类型也可以不包含任何字段,可以为类型关联上一些方法,方法需要有名字,不能被当作值来看待,最重要的是,它必须隶属于某一个类型。方法所属的类型会通过其声明中的接收者(receiver)声明体现出来。

1
2
3
4
5
6
type People struct {
}

func (p People) GetName() string {
return ""
}

方法的基本语法和使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import "fmt"

type People struct {
Name string
Age int
}

func (p People) GetName() string {
return p.Name
}

func main() {
p := People{
Name: "hanpy",
Age: 31,
}
name := p.GetName()
fmt.Println(name)
}

值接收者和指针接收者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package main

import "fmt"

type Person struct {
age int
}

func (p Person) howOld() int {
return p.age
}

func (p *Person) growUp() {
p.age += 1
}

func main() {
// qcrao 是值类型
qcrao := Person{age: 18}

// 值类型 调用接收者也是值类型的方法
fmt.Println(qcrao.howOld())

// 值类型 调用接收者是指针类型的方法
qcrao.growUp()
fmt.Println(qcrao.howOld())

// ----------------------

// stefno 是指针类型
stefno := &Person{age: 100}

// 指针类型 调用接收者是值类型的方法
fmt.Println(stefno.howOld())

// 指针类型 调用接收者也是指针类型的方法
stefno.growUp()
fmt.Println(stefno.howOld())
}

// 18
// 19
// 100
// 101

不管方法的接收者是什么类型,该类型的值和指针都可以调用,不必严格符合接收者的类型。

两者分别在何时使用

如果方法的接收者是值类型,无论调用者是对象还是对象指针,修改的都是对象的副本,不影响调用者;如果方法的接收者是指针类型,则调用者修改的是指针指向的对象本身。

使用指针作为方法的接收者的理由:

  1. 方法能够修改接收者指向的值。
  2. 避免在每次调用方法时复制该值,在值的类型为大型结构体时,这样做会更加高效。

方法继承

匿名字段实现了一个方法,那么包含这个匿名字段的struct也能调用该匿名字段中的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main

import "fmt"

type People struct {
Name string
Age int
}

func (p People) Hello() {
fmt.Printf("Hello Name is %s,Age is %d", p.Name, p.Age)
}

type Student struct {
People
}
type Teacher struct {
People
}

func main() {
s := Student{People{"张学生", 15}}
t := Teacher{People{"李老师", 35}}
// 调用父类方法
s.Hello()
t.Hello()
}

// Hello Name is 张学生,Age is 15
// Hello Name is 李老师,Age is 35

方法重写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package main

import "fmt"

type People struct {
Name string
Age int
}

func (p People) Hello() {
fmt.Printf("Hello Name is %s,Age is %d", p.Name, p.Age)
}

type Student struct {
People
}

func (s Student) Hello() {
fmt.Println("子类的方法-Hello")
}

type Teacher struct {
People
}

func (t Teacher) Hello() {
fmt.Println("子类的方法-Hello")
}

func main() {
s := Student{People{"张学生", 15}}
t := Teacher{People{"李老师", 35}}
// 调用方法(继承父类)
s.Hello()
t.Hello()
}

// 子类的方法-Hello
// 子类的方法-Hello