【Golang】接口、方法、指針、自定義類型-摸清他們的千絲萬縷

主要區(qū)分一下兩個方面的內(nèi)容:

  • 單純的方法定義
  • 通過接口傳遞參數(shù)

1、 單純的方法定義

go語言內(nèi)部會自動進行值和指針的轉(zhuǎn)換, 代碼在編譯的時候不會出錯;區(qū)別在于使用指針定義方法,方法操作的是該數(shù)據(jù)本身;而使用值定義方法時,方法操作的是該數(shù)據(jù)的拷貝。

總結(jié):如果使用除接口類型以外的類型作為接收者時,使用值和指針調(diào)用方法不會出現(xiàn)編譯錯誤; 如果使用接口類型的變量(實現(xiàn)了該接口)調(diào)用方法時,使用值調(diào)用指針定義的方法時會出現(xiàn)編譯出錯。

1、 使用值定義方法,使用值調(diào)用方法的情況

type user struct {
    name string
    email string
}

func (u user) notify() {
    //將傳入的參數(shù)復制一份,賦值給u
    u.name = "Jack"
    fmt.Println("Send email to", u.name, u.email)
}

func main() {
    user := user{"Andy", "1139329@163.com"}
    user.notify()   
    fmt.Println(user)
}

輸出(名子并不會改變):
Send email to Jack 1139329@163.com
{Andy 1139329@163.com}

2、 使用值定義方法,使用指針調(diào)用方法的情況

由于定義方法時使用的是值,在編譯過程中會對調(diào)用者為指針的類型進行解引用,內(nèi)部實現(xiàn)為 *user.notify()

type user struct {
    name string
    email string
}

func (u user) notify() {
    //將傳入的參數(shù)復制一份,賦值給u
    u.name = "Jack"
    fmt.Println("Send email to", u.name, u.email)
}

func main() {
    user := &user{"Andy", "1139329@163.com"}
    user.notify()   
    fmt.Println(user)
}

輸出(名子也不會改變):
Send email to Jack 1139329@163.com
{Andy 1139329@163.com}

3、 使用指針定義方法,使用指針調(diào)用方法的情況

type user struct {
    name string
    email string
}

func (u *user) notify() {
    u.name = "Jack"
    fmt.Println("Send email to", u.name, u.email)
}

func main() {
    user := user{"Andy", "1139329@163.com"}
    user.notify()
    fmt.Println(user)
}

輸出(名子會改變):
Send email to Jack 1139329@163.com
{Jack 1139329@163.com}

4、 使用指針定義方法,使用值調(diào)用方法的情況

內(nèi)部實現(xiàn)為 *user.notify()

type user struct {
    name string
    email string
}

func (u *user) notify() {
    u.name = "Jack"
    fmt.Println("Send email to", u.name, u.email)
}

func main() {
    user := user{"Andy", "1139329@163.com"}
    user.notify()
    fmt.Println(user)
}

輸出(名子會改變):
Send email to Jack 1139329@163.com
{Jack 1139329@163.com}

2、 通過接口傳遞參數(shù)

1、 接受者receiver為值,使用值傳遞的情況

type user struct {
    name  string
    email string
}

type notifyInterface interface {
    notify()
}

func (u user) notify() {
    fmt.Println("Send email to", u.name, u.email)
}

func sendNotification(n notifyInterface) {
    n.notify()
}

func main() {
    user := user{"Andy", "1139329@163.com"}
    sendNotification(user)
}

//編譯成功

2、 接受者receiver為值,使用指針傳遞的情況

type user struct {
    name  string
    email string
}

type notifyInterface interface {
    notify()
}

func (u user) notify() {
    fmt.Println("Send email to", u.name, u.email)
}

func sendNotification(n notifyInterface) {
    n.notify()
}

func main() {
    user := &user{"Andy", "1139329@163.com"}
    sendNotification(user)
}

//編譯成功

3、 接受者receiver為指針,使用指針傳遞的情況

type user struct {
    name  string
    email string
}

type notifyInterface interface {
    notify()
}

func (u *user) notify() {
    fmt.Println("Send email to", u.name, u.email)
}

func sendNotification(n notifyInterface) {
    n.notify()
}

func main() {
    user := &user{"Andy", "1139329@163.com"}
    sendNotification(user)
}

//編譯成功

4、 接受者receiver為指針,使用值傳遞的情況

type user struct {
    name  string
    email string
}

type notifyInterface interface {
    notify()
}

func (u *user) notify() {
    fmt.Println("Send email to", u.name, u.email)
}

func sendNotification(n notifyInterface) {
    n.notify()
}

func main() {
    user := user{"Andy", "1139329@163.com"}
    sendNotification(user)
}

//編譯失敗(使用指針接受者來實現(xiàn)一個接口,值類型無法實現(xiàn)對應的接口)
    cannot use user (type user) as type notifyInterface in argument to sendNotification:
    user does not implement notifyInterface (notify method has pointer receiver)

針對以上情況,《Go語言實戰(zhàn)》一書中這樣講到,首先這是Go語言的一種規(guī)則,具體如下:如果使用指針接受者來實現(xiàn)一個接口,那么只有指向那個類型的指針才能夠實現(xiàn)對應的接口。如果使用值接受者來實現(xiàn)一個接口,那么那個類型的值和指針都能夠實現(xiàn)對應的接口。

為什么會有這樣的限制呢:作者解釋為go編譯器并不總能自動獲得一個值得地址!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,768評論 0 9
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,923評論 18 139
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,210評論 30 471
  • 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,628評論 33 466
  • 想起這個題目,是因為看到了這樣一副照片。 如果仔細看看,照片的廢棄的小木屋上面已經(jīng)有十幾個小圓洞了。 爪米官,一下...
    豎秋閱讀 2,464評論 8 3