1. 程式人生 > >go中的方法到底是個啥

go中的方法到底是個啥

在 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())
}