<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                > Golang 中的方法是作用在指定的數據類型上的(即:和指定的數據類型綁定),因此自定義類型,都可以有方法,`而不僅僅是 struct` [toc] # 1.方法的聲明 Go語言中的方法(Method)是一種作用于特定類型變量的函數。這種特定類型變量叫做接收器(Receiver)。 如果將特定類型理解為結構體或“類”時,接收器的概念就類似于其他語言中的this或者self。 在Go語言中,接收器的類型可以是任何類型,不僅僅是結構體,任何類型都可以擁有方法。 ## 1.1 聲明格式 ``` func (接收器變量 接收器類型) 方法名(參數列表) (返回參數) { 函數體 } ``` - 接收器變量:接收器中的參數變量名在命名時,官方建議使用接收器類型名的第一個小寫字母,而不是self、this之類的命名。例如,Socket類型的接收器變量應該命名為s,Connector類型的接收器變量應該命名為c等。 - 接收器類型:接收器類型和參數類似,可以是指針類型和非指針類型。 - 方法名、參數列表、返回參數:格式與函數定義一致。 ## 1.2 聲明示例 ``` type people struct { Name, Like , Sex string Height, Weight float32 } func (p people) walk() { fmt.Println(p.Name + " 在行走...") } func RunStruct() { var xiaomi people xiaomi.Name = "小明" xiaomi.Name = "小明" p := people{"小明","跑步", "男", 170.0, 62.6} p.walk() } func main() { RunStruct() //out: 小明 在行走... } ``` # 2.接收器分類 ## 2.1 指針類型的接收器 理解指針類型的接收器 指針類型的接收器由一個結構體的指針組成,由于指針的特性,調用方法時,修改接收器指針的任意成員變量,在方法結束后,修改都是有效的。 在下面的例子,使用結構體定義一個屬性(Property),為屬性添加SetValue()方法以封裝設置屬性的過程,通過屬性的Value()方法可以重新獲得屬性的數值。使用屬性時,通過SetValue()方法的調用,可以達成修改屬性值的效果。 ``` 01 package main 02 03 import "fmt" 04 05 // 定義屬性結構 06 type Property struct { 07 value int // 屬性值 08 } 09 10 // 設置屬性值 11 func (p *Property) SetValue(v int) { 12 13 // 修改p的成員變量 14 p.value = v 15 } 16 17 // 取屬性值 18 func (p *Property) GetValue() int { 19 return p.value 20 } 21 22 func main() { 23 24 // 實例化屬性 25 p := new(Property) 26 27 // 設置值 28 p.SetValue(100) 29 30 // 打印值 31 fmt.Println(p.GetValue()) 32 // out: 100 33 } ``` 代碼說明如下: - 第6行,定義一個屬性結構,擁有一個整型的成員變量。 - 第11行,定義屬性值的方法。 - 第14行,設置屬性值方法的接收器類型為指針。因此可以修改成員值,即便退出方法,也有效。 - 第18行,定義獲取值的方法。 - 第25行,實例化屬性結構。 - 第28行,設置值。此時成員變量變為100。 - 第31行,獲取成員變量。 ## 2.2 非指針類型的接收器 當方法作用于非指針接收器時,Go語言會在代碼運行時將接收器的值復制一份。在非指針接收器的方法中可以獲取接收器的成員值,但修改后無效。 點(Point)使用結構體描述時,為點添加Add()方法,這個方法不能修改Point的成員X、Y變量,而是在計算后返回新的Point對象。Point屬于小內存對象,在函數返回值的復制過程中可以極大地提高代碼運行效率,詳細過程請參考下面的代碼。 ``` 01 package main 02 03 import ( 04 "fmt" 05 ) 06 07 // 定義點結構 08 type Point struct { 09 X int 10 Y int 11 } 12 13 // 非指針接收器的加方法 14 func (p Point) Add(other Point) Point { 15 16 // 成員值與參數相加后返回新的結構 17 return Point{p.X + other.X, p.Y + other.Y} 18 } 19 20 func main() { 21 22 // 初始化點 23 p1 := Point{1, 1} 24 p2 := Point{2, 2} 25 26 // 與另外一個點相加 27 result := p1.Add(p2) 28 29 // 輸出結果 30 fmt.Println(result) 31 // out: {3 3} 32 } ``` 代碼說明如下: - 第8行,定義一個點結構,擁有X和Y兩個整型分量。 - 第14行,為Point結構定義一個Add()方法。 - 第23和24行,初始化兩個點p1和p2。 - 第27行,將p1和p2相加后返回結果。 - 第30行,打印結果。 `由于例子中使用了非指針接收器,Add()方法變得類似于只讀的方法,Add()方法內部不會對成員進行任何修改。` ## 2.3 指針和非指針接收器的使用 - 小對象由于值復制時的速度較快,適合使用非指針接收器。 - 大對象因為復制性能較低,適合使用指針接收器,在接收器和參數間傳遞時不進行復制,只是傳遞指針。 # 3. 嵌入結構體擴展類型 結構體允許其成員字段在聲明時沒有字段名而只有類型,這種形式的字段被稱為類型內嵌或匿名字段 類型內嵌的寫法如下: ``` 01 type Data struct { 02 int 03 float32 04 bool 05 } 06 07 ins := &Data{ 08 int: 10, 09 float32: 3.14, 10 bool: true, 11 } ``` 代碼說明如下: - 第2~4行定義結構體中的匿名字段,類型分別是整型、浮點、布爾。 - 第8~10行將實例化的Data中的字段賦初值。 類型內嵌其實仍然擁有自己的字段名,只是字段名就是其類型本身而已,`結構體要求字段名稱必須唯一,因此一個結構體中同種類型的匿名字段只能有一個`。結構體實例化后,如果匿名的字段類型為結構體,那么可以直接訪問匿名結構體里的所有成員,這種方式被稱為結構體內嵌。 ## 3.1 結構內嵌特性 Go語言的結構體內嵌有如下特性。 ### 3.1.1 內嵌的結構體可以直接訪問其成員變量 嵌入結構體的成員,可以通過外部結構體的實例直接訪問。如果結構體有多層嵌入結構體,結構體實例訪問任意一級的嵌入結構體成員時都只用給出字段名,而無須像傳統結構體字段一樣,通過一層層的結構體字段訪問到最終的字段。例如,ins.a.b.c的訪問可以簡化為ins.c。 ### 3.1.2 內嵌結構體的字段名是它的類型名 內嵌結構體字段仍然可以使用詳細的字段進行一層層訪問,內嵌結構體的字段名就是它的類型名, 代碼如下: ``` ... type people struct { Name, Sex string Height, Weight float32 } type boy struct { people Like string } func RunStruct() { var b1 boy b1.Height = 175 //詳細的字段進行一層層訪問 fmt.Println(b1.people.Height) } ``` 一個結構體只能嵌入一個同類型的成員,無須擔心結構體重名和錯誤賦值的情況,編譯器在發現可能的賦值歧義時會報錯。 ## 3.2 使用組合描述對象特性 Go語言的結構體內嵌特性就是一種組合特性,使用組合特性可以快速構建對象的不同特性。 下面的代碼使用Go語言的結構體內嵌實現對象特性組合,請參考代碼6-10。 代碼6-10 人和鳥的特性(具體文件:.../chapter06/humanbird/humanbird.go) ``` 01 package main 02 03 import "fmt" 04 05 // 可飛行的 06 type Flying struct{} 07 08 func (f *Flying) Fly() { 09 fmt.Println("can fly") 10 } 11 12 // 可行走的 13 type Walkable struct{} 14 15 func (f *Walkable) Walk() { 16 fmt.Println("can calk") 17 } 18 19 // 人類 20 type Human struct { 21 Walkable // 人類能行走 22 } 23 24 // 鳥類 25 type Bird struct { 26 Walkable // 鳥類能行走 27 Flying // 鳥類能飛行 28 } 29 30 func main() { 31 32 // 實例化鳥類 33 b := new(Bird) 34 fmt.Println("Bird: ") 35 b.Fly() 36 b.Walk() 37 38 // 實例化人類 39 h := new(Human) 40 fmt.Println("Human: ") 41 h.Walk() 42 43 } //運行結果 Bird: can fly can calk Human: can calk ``` 代碼說明如下: - 第6行,聲明可飛行結構(Flying)。 - 第8行,為可飛行結構添加飛行方法Fly()。 - 第13行,聲明可行走結構(Walkable)。 - 第15行,為可行走結構添加行走方法Walk()。 - 第20行,聲明人類結構。這個結構嵌入可行走結構(Walkable),讓人類具備“可行走”特性 - 第25行,聲明鳥類結構。這個結構嵌入可行走結構(Walkable)和可飛行結構(Flying),讓鳥類具備既可行走又可飛行的特性。 - 第33行,實例化鳥類結構。 - 第35和36行,調用鳥類可以使用的功能,如飛行和行走。 - 第39行,實例化人類結構。 - 第41行,調用人類能使用的功能,如行走。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看