go語言學習-介面賦值

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

在go語言中,介面賦值分為2中情況:

1、將對象執行個體賦值給介面;

2、將一個介面賦值給另一個介面。

 

1、將對象執行個體賦值給介面:

       要求對象實現了介面的所有方法。

 

2、將介面賦值給另一個介面:

       假設介面A中定義的所有方法,都在介面B中有定義,那麼B介面的執行個體可以賦值給A的對象。反之不成立,除非A和B定義的方法完全一樣(順序不要求),這時A和B等價,可以相互賦值。

 

3、類執行個體化時指標或者執行個體區別:

       執行個體化類的時候,一般有2個方法:

(1) 用new(structName):這個方法得到的是*structName類型,即類的指標類型;

(2) 用structName{init para}:這個方法得到的是structName類型,即類的執行個體類型,不是指標。

 

 

注意:

類在實現介面的時候,要注意定義的時候,一般用類的指標傳入,就可以了。因為如果用類的結構體的話,可能會導致“類沒有實現介面中某個方法”的錯誤。詳細舉例:

 

packagemain

import"fmt"

 

typetmpInterfaceinterface{

    tmpFunc()

    tmpFuncPtr()

}

 

typetmpStructstruct{

 

}

 

func(ttmpStruct)tmpFunc(){

    fmt.Println("functmpFunc")

}

 

func(t*tmpStruct)tmpFuncPtr(){

    fmt.Println("functmpFuncPtr")

}

 

funcmain(){

    /*這裡如果用new,則得到的是tmpStruct的指標,tmpInterface的2個方法都可用*/

    vart_ttmpInterface=new(tmpStruct)

    t_t.tmpFunc()

    t_t.tmpFuncPtr()

 

    /*這裡如果用tmpStruct{},則得到的是tmpStruct的執行個體,tmpInterface的2個方法都可用*/

/*

    vart_ptrtmpInterface=tmpStruct{}

    t_ptr.tmpFunc()

    t_ptr.tmpFuncPtr()

*/

}

 

上面的main()函數中,如果用tmpStruct{}初始化(可以理解為建構函式,沒有入參),得到的是 tmpStruct的類型,會編譯出錯:

cannot use tmpStruct literal(type tmpStruct) as type tmpInterface in assignment:tmpStruct does not implementtmpInterface(tmpFuncPtr method has pointer receiver)

 

個人理解:

    受之前對C++或者JAVA等物件導向語言的影響,我們會把定義類的代碼(以及其方法)視為一體的,下面把代碼再複製一份下來:

typetmpStructstruct{

 

}

func(ttmpStruct)tmpFunc(){

    fmt.Println("functmpFunc")

}

func(t*tmpStruct)tmpFuncPtr(){

    fmt.Println("functmpFuncPtr")

}

 

        如果把上面這些代碼理解成C++中對類tmpStruct的定義,函數tmpFunc和tmpFuncPtr是類的2個成員函數,那麼會難以理解為什麼又會提示tmpStruct沒有實現tmpFuncPtr這個方法的提示。

    其實go語言中,interface和struct之間的關係和傳統的物件導向中的是非常不一樣的,介面和類之間耦合度非常低。同時,對其之間關係起到串連作用的“成員函數”,個人感覺和類以及介面的耦合度也是非常低的,倒不如直接把這些“成員函數”直接理解成普通的方法,只是go語言中允許這樣的特殊文法形式定義:

關鍵字        傳入的類/類指標     正常的函數定義

func           (t tmpStruct)      tmpFunc() {…}

func           (t *tmpStruct)     tmpFuncPtr(){…}

 

        在用類的執行個體/執行個體指標初始化介面的對象時:

vart_ttmpInterface=new(tmpStruct)

由於new返回的是一個指標,所以這裡相當於t_t是一個*tmpStruct類型的變數,所以在調用函數的時候,給函數傳入的就是一個指標。

    摘抄一句《Go語言編程》裡面的話(3.5.3:介面賦值):

           Go語言可以根據下面的函數:

func (a Integer) Less(b Integer) bool

自動產生一個新的Less()方法:

func (a *Integer) Less(b Integer) bool {…}

    就是說,有了結構體類型作為入參的函數,go語言會自動建立一個相應的指標作為入參的函數,但是只有指標入參的函數,不會建立相應的結構體類型的函數。

   

    如果這樣定義:

vart_ptrtmpInterface=tmpStruct{}

    tmpStruct{}的結果是tmpStruct類型,如果允許賦值給t_ptr成功的話,那麼調用t_ptr.tmpFuncPtr時因為傳入類型錯誤,所以這個角度看,go直接讓編譯不通過也是可以理解的。

 

 

 

總結:如果類的“成員函數”中有傳入結構體指標類型的,則必須用結構體指標類型執行個體化介面的執行個體。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.