在 Go 语言里,方法和函数只差了一个,那就是方法在 func 和标识符之间多了一个参数。
type user struct {
name string,
email string,
}
//这是函数的定义
func notify(email string) {
fmt.Println("Email is %s", email)
}
//这是方法的定义
func (u user) notify(email string) {
fmt.Println("Email is %d", email)
}
我们可以看到,方法是在 func 和 notify 之间多了一个 user 类型的参数 u,这个 u 就称作接收者。
首先,我们是先要定义一个类型,比如就是 user 好了,然后我们再定义方法。
type user struct {
name string
email string
}
func (u user) notify() {
fmt.Println("Email is %d", u.email)
}
func (u *user) changeEmail(email string) {
u.email = email
}
我们定义了两个方法,一个是 notify,它是值接收者方法;还有一个是 changeEmail,它是指针接收者方法。可以看到,值接收者方法,接收者是一个副本,无法修改;指针接收者是引用,可以修改。
值接收者方法:
package main
import (
"fmt"
)
type Vertex struct {
X, Y float64
}
func (v Vertex)Abs() {
v.Y=66
v.X=66666
}
func main() {
v := Vertex{3, 4}
fmt.Println(v)
v.Abs()
fmt.Println(v)
}
输出:
{3 4}
{3 4}
指针接收者方法:
package main
import (
"fmt"
)
type Vertex struct {
X, Y float64
}
func (v *Vertex)Abs() {
v.Y=66
v.X=66666
}
func main() {
v := Vertex{3, 4}
fmt.Println(v)
v.Abs()
fmt.Println(v)
}
输出:
{3 4}
{66666 66}
我们再来看一下调用。
daryl := {"daryl", "[email protected]"}
daryl.changeEmail("[email protected]")
daryl.notify()
看看,是不是很熟悉! daryl 就是对象,name 和 email 就是属性,notify 和 changeEmail 就是它的方法。只是,不同的是,我们没有将它放到 class 中,而是用另外一种方式让它们结合了,有了关系!
方法声明时要注意以下几点:
1.接收者的类型定义和方法声明必须在同一包内
查看项目结构:
我们在包1内的hello.go内创建了个struct结构,在method1.go内创建了M1方法,在包2下面的method2.go文件内也创建了M1方法,其中method1.go的M1方法创建成功,method2.go的M1方法创建失败。
2.不能为内建类型声明方法
//这样是可以的
type MyFloat float64
func (f MyFloat) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
func main() {
f := MyFloat(-math.Sqrt2)
fmt.Println(f.Abs())
}
//不能为内建类型创建方法
func (f float64) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
func main() {
f := float64(-math.Sqrt2)
fmt.Println(f.Abs())
}