Hi,你們好,我是明哥。git
在本身學習 Golang 的這段時間裏,我寫了詳細的學習筆記放在個人我的微信公衆號 《Go編程時光》,對於 Go 語言,我也算是個初學者,所以寫的東西應該會比較適合剛接觸的同窗,若是你也是剛學習 Go 語言,不防關注一下,一塊兒學習,一塊兒成長。github
個人在線博客:http://golang.iswbm.com
個人 Github:github.com/iswbm/GolangCodingTimegolang
接口是一組固定的方法集,因爲靜態類型的限制,接口變量有時僅能調用其中特定的一些方法。編程
請看下面這段代碼微信
package main import "fmt" type Phone interface { call() } type iPhone struct { name string } func (phone iPhone)call() { fmt.Println("Hello, iPhone.") } func (phone iPhone)send_wechat() { fmt.Println("Hello, Wechat.") } func main() { var phone Phone phone = iPhone{name:"ming's iphone"} phone.call() phone.send_wechat() }
我定義了一個 Phone 的接口,只要求實現 call 方法便可,也就是隻要能打電話的設備就是一個電話(好像是一句沒用的廢話)。iphone
而後再定義了一個 iPhone 的結構體,該結構體接收兩個方法,一個是打電話( call 函數),一個是發微信(send_wechat 函數)。函數
最後一步是關鍵,咱們定義了一個 Phone 接口類型的 phone 對象,該對象的內容是 iPhone 結構體。而後咱們調用該對象的 call 方法,一切正常。學習
可是當你調用 phone.send_wechat
方法,程序會報錯,提示咱們 Phone 類型的方法沒有 send_wechat 的字段或方法。3d
# command-line-arguments ./demo.go:30:10: phone.send_wechat undefined (type Phone has no field or method send_wechat)
緣由也很明顯,由於咱們的phone對象顯示聲明爲 Phone 接口類型,所以 phone調用的方法會受到此接口的限制。code
那麼如何讓 phone 能夠調用 send_wechat 方法呢?
答案是能夠不顯示的聲明爲 Phone接口類型 ,但要清楚 phone 對象其實是隱式的實現了 Phone 接口,如此一來,方法的調用就不會受到接口類型的約束。
修改 main 方法成以下
func main() { phone := iPhone{name:"ming's iphone"} phone.call() phone.send_wechat() }
運行後,一切正常,沒有報錯。
Hello, iPhone. Hello, Wechat.
Go 語言中的函數調用都是值傳遞的,變量會在方法調用前進行類型轉換。
好比下面這段代碼
import ( "fmt" ) func printType(i interface{}) { switch i.(type) { case int: fmt.Println("參數的類型是 int") case string: fmt.Println("參數的類型是 string") } } func main() { a := 10 printType(a) }
若是你運行後,會發現一切都很正常
參數的類型是 int
可是若是你把函數內的內容搬到到外面來
package main import "fmt" func main() { a := 10 switch a.(type) { case int: fmt.Println("參數的類型是 int") case string: fmt.Println("參數的類型是 string") } }
就會有意想不到的結果,竟然報錯了。
# command-line-arguments ./demo.go:9:5: cannot type switch on non-interface value a (type int)
這個操做會讓一個新人摸不着頭腦,代碼邏輯都是同樣的,爲何一個不會報錯,一個會報錯呢?
緣由其實很簡單。
當一個函數接口 interface{} 空接口類型時,咱們說它能夠接收什麼任意類型的參數(江湖上稱之爲無招勝有招)。
當你使用這種寫法時,Go 會默默地爲咱們作一件事,就是把傳入函數的參數值(注意:Go 語言中的函數調用都是值傳遞的)的類型隱式的轉換成 interface{} 類型。
上面瞭解了函數中 接口類型的隱式轉換後,你的內心可能開始有了疑問了,難道我使用類型斷言,只能經過一個接收空接口類型的函數才能實現嗎?
答案固然是 No.
若是你想手動對其進行類型轉換,能夠像下面這樣子,就能夠將變量 a 的靜態類型轉換爲 interface{} 類型而後賦值給 b (此時 a 的靜態類型仍是 int,而 b 的靜態類型爲 interface{})
var a int = 25 b := interface{}(a)
知道了方法後,將代碼修改爲以下:
package main import "fmt" func main() { a := 10 switch interface{}(a).(type) { case int: fmt.Println("參數的類型是 int") case string: fmt.Println("參數的類型是 string") } }
運行後,一切正常。
參數的類型是 int
上面咱們知道了,只有靜態類型爲接口類型的對象才能夠進行類型斷言。
而當類型斷言完成後,會返回一個靜態類型爲你斷言的類型的對象,也就是說,當咱們使用了類型斷言,Go 實際上又會默認爲咱們進行了一次隱式的類型轉換。
驗證方法也很簡單,使用完一次類型斷言後,對返回的對象再一次使用類型斷言,Goland 立馬就會提示咱們新對象 b 不是一個接口類型的對象,不容許進行類型斷言。