# 方法
* * * * *
--: 作者:jsh
時間:2018年9月9日
* * * * *
在 Go 語言中,結構體就像是類的一種簡化形式,那么面向對象程序員可能會問:類的方法在哪里呢?在 Go 中有一個概念,它和方法有著同樣的名字,并且大體上意思相同:Go 方法是作用在接收者(user)上的一個函數,接收者是某種類型的變量。Go 語言中同時有函數和方法。一個方法就是一個包含了接受者的函數,接受者可以是命名類型或者結構體類型的一個值或者是一個指針
方法能給用戶定義的類型添加新的行為。方法實際上也是函數,只是在聲明時,在關鍵字 func和方法名之間增加了一個參數。
### 方法
定義方法的一般格式如下:
~~~
func (u user) methodName(parameter_list) (return_value_list) { ... } // 使用值接收者方法
func (u *user) methodName(parameter_list) (return_value_list) { ... } // 使用指針接收者方法
~~~
案例一:值接收者
~~~
type user struct {
name string,
email string,
}
func (u user) notify() {
fmt.Println("Email is %d", u.email)
}
func main() {
jsh := {"jsh", "jsh@163.com"}
jsh.notify()
}
~~~
值接收者,是接收者的類型是一個值,是一個副本,方法內部無法對其真正的接收者做更改,上面的代碼中我們定義了一個notify方法,notify方法的接收者被聲明為user類型的值。如果使用值接收者聲明方法,調用時會使用這個值的副本。
案例二:指針接收者
~~~
type user struct {
name string,
email string,
}
func (u *user) changeEmail(email string) {
u.email = email
}
func main() {
jsh := {"jsh", "jsh@163.com"}
jsh.changeEmail("jsh@163.com")
}
~~~
指針接收者,接收者的類型是一個指針,是接收者的引用,對這個引用的修改之間影響真正的接收者。像上面一樣定義方法,將 user 改成 *user 就是指針接收者,changeEmail它是指針接收者方法。可以看到,值接收者方法,接收者是一個副本,無法修改;指針接收者是引用,可以修改。
### 值類型
所有像int、float、bool和string這些類型都屬于值類型,使用這些類型的變量直接指向存在內存中的值,值類型的變量的值存儲在棧中。當使用等號=將一個變量的值賦給另一個變量時,如 j = i ,實際上是在內存中將 i 的值進行了拷貝。可以通過&i獲取變量 i 的內存地址
```
package main
import "fmt"
func main(){
a := [5]int{2, 3, 4, 5, 6}
b := a
fmt.Println(a,b)
b[2] = 77
fmt.Println(a,b)
}
```
定義了一個數組a,它是值類型,復制給b是copy,當b發生變化后a并會不會發生任何變化呢?
### 引用類型
復雜的數據通常會需要使用多個字,這些數據一般使用引用類型保存。一個引用類型的變量a存儲的是a的值所在的內存地址(數字),或內存地址中第一個字所在的位置,這個內存地址被稱之為指針,這個指針實際上也被存在另外的某一個字中。
```
package main
import "fmt"
func main(){
a := []int{2, 3, 4, 5, 6}
b := a
fmt.Println(a,b)
b[2] = 77
fmt.Println(a,b)
}
```
定義一個切片a,然后將切片a復制給b,當修改b的值的時候a會不會發生變化呢?