Go method

方法 Method

Go 中虽然没有class,但依旧有method,通过显示说明receiver来实现与某个类型的组合,只能为同一个包中的类型定义方法,receiver可以是类型的值或指针。

method不存在方法重载,可以是使用值或指针来调节方法,编译器会自动完成转换,从某种意义上来说,方法是函数的语法糖,因为receiver其实就是方法所接收的第一个参数(Method Value vs Method Expression)

如果外部结构和嵌入结构存在同名方法,则优先调用外部结构的方法,类型别名不会拥有底层类型所附带的方法。

方法可以待用结构中的非公开字段

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
type SysUser struct {
name string
}

func (user SysUser) ToString() {
user.name = "123"
fmt.Println(user.name)
}

func main() {
user := SysUser{name: "1"}
user.ToString()
}

输出

1
123

其中ToString接收体是SysUser

不存在重载,通过类型绑定区分

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
type SysUser struct {
name string
}

type SysOrg struct {
name string
}

func (user SysUser) ToString() {
user.name = "123"
fmt.Println(user.name)
}

func (org SysOrg) ToString() {
org.name = "321"
fmt.Println(org.name)
}

func main() {
user := SysUser{name: "1"}
user.ToString()

org := SysOrg{name: "2"}
org.ToString()
}

输出

1
2
123
321

在这里,ToString分别绑定了SysUserSysOrg,区分开了2种。

以下这种是不行的,以下函数针对同一个类型,区分不出来用户使用那一个。

1
2
3
4
5
6
7
8
9
func (user SysUser) ToString() {
user.name = "123"
fmt.Println(user.name)
}

func (user SysUser) ToString(i int) {
user.name = i
fmt.Println(user.name)
}

编译错误:

1
2
3
4
5
6
7
# command-line-arguments
: method redeclared: SysUser.ToString
method(SysUser) func()
method(SysUser) func(int)
: SysUser.ToString redeclared in this block
previous declaration at .....
.....: cannot use i (type int) as type string in assignment

可以是值或指针

如果是值类型,只是拷贝值,进行值传递。如果是指针类型,最终会影响到地址对应的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func (user *SysUser) ToString() {
user.name = "123"
fmt.Println(user.name)
}

func (org SysOrg) ToString() {
org.name = "321"
fmt.Println(org.name)
}

func main() {
user := SysUser{name: "1"}
user.ToString()
fmt.Println(user)

org := SysOrg{name: "2"}
org.ToString()
}

输出

1
2
3
123
{123}
321

可以看到值发生了改变

底层类型

1
2
3
4
5
6
7
8
9
10
type TZ int

func (a *TZ) Print() {
fmt.Println("TZ")
}

func main() {
var a TZ
a.Print()
}

输出

1
TZ

底层类型就可以自由加入方法的绑定

对比

Method Value

通过值进行调用

1
2
var a TZ
a.Print()

Method Expression

通过一种类型进行调用

1
(*TZ).Print(&a)

方法访问权限与字段

1
2
3
4
type A struct{
name string
Age int
}

在同一个包内就可以进行访问,修改。当超出包的范围后,只有首字母大写字段暴露出去。

练习

声明一个底层类型为int的类型,并实现调用方法递增到100

1
2
3
4
5
6
7
8
9
func (a *TZ) Increase(num int) {
*a += TZ(num)
}

func main() {
var a TZ
a.Increase(100)
fmt.Print(a)
}

输出

1
100
- the End -
0%