Go 結構體方法

#### Go 結構體方法
原本今天有些事情忙的不許備更新內容了,後來提早完成了, 因此仍是要更新了;
畢竟堅持本就是一件不容易的事情!加油,相信無論是你們仍是我,都有一些事情想要作,那就堅持吧,剩下的交給天意吧;
昨天到今天上午一直在處理微信我的帳戶支付的事情,***大概就是若是我的沒有能力或者沒有權限開通微信支付功能,
而又想用微信的支付功能,那可能須要一些特殊的處理, 支付寶的功能同上***;
若是你們對我的支付感興趣的,能夠找我哈^_^;
在這裏給你們推薦一首歌
原唱: 趙方婧
---
##### 方法
在一些狀況下定義方法: 如結構體的行爲,須要用方法才能完成;
Go 中的方法是做用在指定的數據類型上的(和指定的數據類型綁定),所以***自定義類型均可以有方法,不單單是結構體***;
方法的聲明與調用:
type A struct {
Name string
}
func (a A) say(){
fmt.Println(a.Name)
}
說明:
1. func(a A) say() {} 表示結構體A有一個方法,名稱爲say
2. (a A) 體現say 方法與A 類型綁定
案例:
package main

import "fmt"

type Person struct {
   Name string
   Age int
}
func (p Person) say(){
   fmt.Printf("I am %s and %d years old\n",p.Name,p.Age)
}
func main(){
   var p Person
   p.Name = "aaa"
   p.Age = 11
   var p2 Person
   p2.Name = "bbb"
   p2.Age = 22
   // 調用實例方法
   p.say() // I am aaa and 11 years old
   p2.say() //I am bbb and 22 years old
}

  


說明:
1. say 方法與Person 類型綁定
2. say 方法只能經過Person 類型的變量來調用,不能直接調用,也不能使用其它類型的變量調用;
3. say 方法的調用方式與其它OOP 語言有很大不一樣,***沒有靜態方法***;
4. func (p Person) say(){} p 表示哪一個Person 實例調用,這個p 就是它的副本,與函數傳參類似;
5. p***稱爲接收者***,能夠自定義,通常建議起一些能夠直觀體驗類型的名字;
---
再來體驗一下例子:
package main

import (
   "fmt"
)
type Student struct {
   Name string
   Age int
   Skills []string
}
// 這裏相似引用
func (s *Student)Learn(skill string) {
   // 經過學習,會一個技能
   // append 底層會自動make
   s.Skills = append(s.Skills,skill)
}
func (s Student) Show(){
   for _,skill := range s.Skills {
      fmt.Printf("I am %s,I am %d years old,and %sing is my skill\n",s.Name,s.Age,skill)
   }
}
func main(){
   var s1 Student
   s1.Name = "小明"
   s1.Age = 20
   s1.Learn("fish")
   s1.Learn("learn")
   var s2 Student
   s2.Name = "小紅"
   s2.Age = 18
   s2.Learn("Sing")
   s2.Learn("paint")
   // 調用方法
   s1.Show()
   s2.Show()
   //I am 小明,I am 20 years old,and fishing is my skill
   //I am 小明,I am 20 years old,and learning is my skill
   //I am 小紅,I am 18 years old,and Singing is my skill
   //I am 小紅,I am 18 years old,and painting is my skill
}

  


說明:
上面的一個小例子裏面綜合了前面學習的知識,還有本節要學習的知識,學習完本節應該都能理解了;
##### 方法的調用與傳參機制原理
方法的調用和傳參機制和函數基本同樣,不同的地方是方法調用時,會將調用方法的變量當作實參也傳遞給方法;
若是接收者是值類型進行值拷貝,若是接收者是引用類型進行地址拷貝;
package main

import "fmt"
type Student struct {
   Name string
   Age int
}
func (s Student) setName(){
   // 接收者爲實例變量的副本,在方法內更改值不會影響原來的值
   s.Name = "aaaaaa"
}
func (s *Student) setAge(){
   // 接收者爲實例變量地址的副本,在方法內更改值會改變原來的值
   s.Age = 21
}
func main(){
   var s1 Student
   var s2 Student
   s1.Name = "a"
   s1.Age = 10
   s2.Name = "b"
   s2.Age = 10
   s1.setName()
   fmt.Println(s1)// {a 10}
   s2.setAge()
   fmt.Println(s2) //{b 21}
}

  


方法的注意事項:
1. 結構體是值類型,在方法調用中遵照值類型的傳遞機制;
2. 若是須要修改結構體變量的值,相似上述例子,經過結構體指針的方式處理;
3. Go 中的方法做用在指定的數據類型的方法上(與指定的數據類型綁定);
4. 方法的控制範圍的規則與函數同樣,方法名首字母小寫,只能在本包內訪問,方法首字母大寫,能夠在本包和其它包訪問;
5. 若是一個結構體實現了String() 方法,那麼fmt.Println() 默認會調用String 方法進行輸出;
6. 對於方法接收者是值類型時,能夠直接用指針類型的變量調用,反過來一樣能夠;
7. 無論接收者是值類型仍是引用類型均可以直接使用實例變量調用方法;
案例:
package main

import "fmt"
type Student struct {
   Name string
   Age int
}
//也可使用值類型調用此方法
func (s *Student) setName(){
   s.Name = "bbbb"
}
//也可使用指針類型調用此方法
func (s Student) showName(){
   fmt.Println(s.Name)
}
// 默認fmt.Println 會調用此方法
func (s Student) String() string{
   return fmt.Sprintf("I am %s,i am %d years old",s.Name,s.Age)
}
func main(){
   var s Student
   s.Name = "a"
   s.Age = 20
   fmt.Println(s) // I am a,i am 20 years old
   s.setName() // 值類型的調用接收者爲指針類型的方法
   s.showName() // bbbb
   fmt.Println(s) // I am bbbb,i am 20 years old
   var s1 *Student = new(Student)
   s1.Name = "b"
   s1.Age = 10
   fmt.Println(s1) // I am b,i am 10 years old
   s1.setName() //
   s1.showName() // bbbb 指針類型的調用接收者爲值類型的方法
   // 在這裏須要說一下
    // 標準的調用 方式應該是
    (*s1).showName()
    // Go 編譯器在底層自動作了解引用,因此能夠簡化成s1.showName 
    // 總之,無論是指針接收者仍是值接收者,統一使用實例.方法名就能夠; 
   fmt.Println(s1) //I am bbbb,i am 10 years old
}

  


---
總結一下:
無論調用形式如何(調用者是值類型仍是引用類型),真正決定是值拷貝仍是地址拷貝的,要看方法的接收者是什麼類型;
如: (p Person) 則進行的是值拷貝,(p *Person) 是地址拷貝;
今天這些內容,有點繞,暫時就這些吧,學習一種新的編程語言時須要將其它的編程風格摒棄掉,但願一塊兒進步;
我的微信公衆號上會發最新的內容,歡迎關注一同交流學習

相關文章
相關標籤/搜索