## 方法和接收者
Go語言中的方法(Method)是一種作用于特定類型變量的函數。這種特定類型變量叫做接收者(Receiver)。接收者的概念就類似于其他語言中的this或者 self。
方法的定義格式如下:
~~~
func (接收者變量 接收者類型) 方法名(參數列表) (返回參數) {
函數體
}
~~~
特性:
? 只能為當前包內命名類型定義方法;
? 參數 receiver 可任意命名,如方法中未曾使用 ,可省略參數名;
? 參數 receiver 類型可以是 T 或 *T。基類型 T 不能是接口或指針;
? 不支持方法重載,receiver 只是參數簽名的組成部分;
? 接收者變量:接收者中的參數變量名在命名時,官方建議使用接收者類型名的第一個小寫字母,而不是self、this之類的命名。例如,Person類型的接收者變量應該命名為 p,Connector類型的接收者變量應該命名為c等;
? 接收者類型:接收者類型和參數類似,可以是指針類型和非指針類型(編譯器自動轉換);
~~~
//Person 結構體
type Person struct {
name string
age int8
}
//NewPerson 構造函數
func NewPerson(name string, age int8) *Person {
return &Person{
name: name,
age: age,
}
}
func (p Person) Dream() {
fmt.Printf("%s的夢想是學好Go語言!\n", p.name)
}
// 指針調用,為避免內存拷貝,通常使用該方式
func (p *Person) Running() {
fmt.Printf("%s在跑步!", p.name)
}
func main() {
p1 := NewPerson("測試", 25)
p1.Dream()
}
~~~
### 指針類型接收者適用場景
~~~
1. 適用于對方法內部的接收器所做的改變應該對調用者可見時
2. 接收者是拷貝代價比較大的大對象
3. 保證一致性,如果有某個方法使用了指針接收者,那么其他的方法也應該使用指針接收者
~~~
### 匿名字段的方法
屬于結構體的匿名字段的方法可以被直接調用,就好像這些方法是屬于定義了匿名字段的結構體一樣
~~~go
type address struct {
city string
state string
}
func (a address) fullAddress() {
fmt.Printf("Full address: %s, %s", a.city, a.state)
}
type person struct {
firstName string
lastName string
address
}
func main() {
p := person{
firstName: "Elon",
lastName: "Musk",
address: address {
city: "Los Angeles",
state: "California",
},
}
p.fullAddress() //訪問 address 結構體的 fullAddress 方法
}
~~~
### 在非結構體上的方法
到目前為止,我們只在結構體類型上定義方法。也可以在非結構體類型上定義方法,但是有一個問題。為了在一個類型上定義一個方法,方法的接收器類型定義和方法的定義應該在同一個包中。到目前為止,我們定義的所有結構體和結構體上的方法都是在同一個`main`包中,因此它們是可以運行的
~~~go
package main
func (a int) add(b int) {
}
func main() {
}
// 在上面程序中,我們嘗試把一個`add`方法添加到內置的類型`int`。這是不允許的,因為`add`方法的定義和`int`類型的定義不在同一個包中。該程序會拋出編譯錯誤`cannot define new methods on non-local type int`
~~~
讓該程序工作的方法是為內置類型 int 創建一個類型別名,然后創建一個以該類型別名為接收器的方法。
~~~go
package main
import "fmt"
type myInt int
func (a myInt) add(b myInt) myInt {
return a + b
}
func main() {
num1 := myInt(5)
num2 := myInt(10)
sum := num1.add(num2)
fmt.Println("Sum is", sum)
}
~~~
- 概述
- go語言基礎特性
- Go語言聲明
- Go項目構建及編譯
- go command
- 程序設計原則
- Go基礎
- 變量
- 常量
- iota
- 基本類型
- byte和rune類型
- 類型定義和類型別名
- 數組
- string
- 高效字符串連接
- string底層原理
- 運算符
- new
- make
- 指針
- 下劃線 & import
- 語法糖
- 簡短變量申明
- 流程控制
- ifelse
- switch
- select
- select實現原理
- select常見案例
- for
- range
- range實現原理
- 常見案例
- range陷阱
- Goto&Break&Continue
- Go函數
- 函數
- 可變參數函數
- 高階函數
- init函數和main函數
- 匿名函數
- 閉包
- 常用內置函數
- defer
- defer常見案例
- defer規則
- defer與函數返回值
- defer實現原理
- defer陷阱
- 數據結構
- slice
- slice內存布局
- slice&array
- slice底層實現
- slice陷阱
- map
- Map實現原理
- 集合
- List
- Set
- 線程安全數據結構
- sync.Map
- Concurrent Map
- 面向對象編程
- struct
- 匿名結構體&匿名字段
- 嵌套結構體
- 結構體的“繼承”
- struct tag
- 行為方法
- 方法與函數
- type Method Value & Method Expressions
- interface
- 類型斷言
- 多態
- 錯誤機制
- error
- 自定義錯誤
- panic&recover
- reflect
- reflect包
- 應用示例
- DeepEqual
- 反射-fillObjectField
- 反射-copyObject
- IO
- 讀取文件
- 寫文件
- bufio
- ioutil
- Go網絡編程
- tcp
- tcp粘包
- udp
- HTTP
- http服務
- httprouter
- webSocket
- go并發編程
- Goroutine
- thread vs goroutine
- Goroutine任務取消
- 通過channel廣播實現
- Context
- Goroutine調度機制
- goroutine調度器1.0
- GMP模型調度器
- 調度器竊取策略
- 調度器的生命周期
- 調度過程全解析
- channel
- 無緩沖的通道
- 緩沖信道
- 單向信道
- chan實現原理
- 共享內存并發機制
- mutex互斥鎖
- mutex
- mutex原理
- mutex模式
- RWLock
- 使用信道處理競態條件
- WaitGroup
- 工作池
- 并發任務
- once運行一次
- 僅需任意任務完成
- 所有任務完成
- 對象池
- 定時器Timer
- Timer
- Timer實現原理
- 周期性定時器Ticker
- Ticker對外接口
- ticker使用場景
- ticker實現原理
- ticker使用陷阱
- 包和依賴管理
- package
- 依賴管理
- 測試
- 單元測試
- 表格測試法
- Banchmark
- BDD
- 常用架構模式
- Pipe-filter pattern
- Micro Kernel
- JSON
- json-內置解析器
- easyjson
- 性能分析
- gc
- 工具類
- fmt
- Time
- builtin
- unsafe
- sync.pool
- atomic
- flag
- runtime
- strconv
- template