超強總結:Go 語言四種類型轉換方法
大家好,我是明哥。
Go 語言是靜態(tài)語言,在編寫代碼時,就對類型有嚴格的要求,一旦類型不匹配,就有可能編譯失敗。
因此在寫代碼時,就要經(jīng)常用到類型的轉換,這些知識點,對于一個新手來說,可以說是一個不小的門檻,經(jīng)常要通常搜索引擎來尋找答案。
今天我總結了四種日常開發(fā)中最經(jīng)常遇到的類型轉換方法,吃透后就可以自由的進行類型轉換。
# 第一種:顯式類型轉換
使用對應的類型函數(shù)進行轉換,以一個簡單的例子來幫助理解,使用 int16 就可以將 int8 類型的對象轉為 int16
package?main
import?"fmt"
func?main()?{
????var?a?int8?=?5
????fmt.Printf("%T?\n",?a)
????//?output:?int8
????b?:=?int16(a)
????fmt.Printf("%T?\n",?b)
????//?output:?int16
}
再舉個例子,先將 string 類型通過 []byte 類型函數(shù)轉為 []byte (等同于 []uint8),最后又使用 string 類型函數(shù)將 ?[]byte 轉回 string
package?main
import?"fmt"
func?main()?{
????var?s1?string?=?"golang"
????fmt.Printf("%T?\n",?s1)
????//?output:?string
????s2?:=?[]byte(s1)
????fmt.Printf("%T?\n",?s2)
????//?output:?[]uint8
????s3?:=?string(s2)
????fmt.Printf("%T?\n",?s3)
????//?output:?string
}
這種方法,同樣適用于自己定義的結構體和接口類型,但要注意的是,僅能用于將結構體類型轉換接口類型,而不能將接口類型轉為結構體類型。
這邊也舉個例子
package?main
import?"fmt"
type?People?interface?{
????Speak()
}
type?Student?struct?{
????name?string
}
func?(s?Student)?Speak()?{
????fmt.Println("hello,?golang")
}
func?demo2(s?People)?{
????s.Speak()
}
func?demo1(s1?Student)?{
????????//?結構體類型轉為接口類型
????s2?:=?People(s1)
????demo2(s2)
}
func?main()?{
????s1?:=?Student{name:?"wangbm"}
????demo1(s1)
}
# 第二種:隱式類型轉換
隱式轉換,是編譯器所為,在日常開發(fā)中,開發(fā)者并不會感覺到發(fā)生了變化。
隱式轉換以下面兩種情況最為常見,非常簡單,我直接以截圖加標注說明就行了,不再長篇大論。
?函數(shù)調用時轉換

?函數(shù)返回時轉換

# 第三種:類型斷言
學了上面第二種方法后,我們已經(jīng)知道下面這段代碼,肯定是會編譯失敗的。
package?main
import?"fmt"
type?Student?struct?{
????name?string
}
func?(s?Student)?Speak()?{
????fmt.Println("hello,?golang")
}
func?demo2(s?Student)?{
????s.Speak()
}
func?demo1(s1?interface{})?{
????demo2(s1)
}
func?main()?{
????s1?:=?Student{name:?"wangbm"}
????demo1(s1)
}
答案當然是不能了,原因很簡單,因為經(jīng)過 demo1 函數(shù)后,s1 會被隱式轉換成 interface{} 類型,而 demo2 函數(shù)的參數(shù)類型要求為 Student,因此類型不匹配。

解決方法也相當?shù)暮唵危灰褂妙愋蛿嘌砸幌拢湍軐崿F(xiàn)靜態(tài)類型的轉換。

為了避免有新手,還不了解類型斷言(Type Assertion),我這邊再簡單介紹一下。
類型斷言可用于判斷一個對象是否是某類型。
這其中包含兩種情況:
第一種情況:該對象是 T 類型(struct 類型),則斷言該對象是 T 類型,就能斷言成功。
第二種情況:該對象是 I 類型(接口類型),則斷言對象是 T 類型,也能斷言成功,并且返回一個靜態(tài)類型為 T 的對象,也相當于類型轉換了。
倘若類型斷言失敗,則會拋出 panic,使用的時候,請千萬注意處理。若不想讓其拋出 panic,可以使用另一種斷言語法。斷言不是今天的主題,這里不再展開,更多具體內容,請查看我以前的這篇文章 (27. 說說 Go 語言中的類型斷言?),寫的非常清楚。
s,?ok?:=?x.(T)
另外,有一點需要提醒的是,類型斷言并不能用于兩個通用類型的相互轉換,只能用于將靜態(tài)類型為 interface{} 類型的對象,轉為具體的類型。
# 第四種:重新構造對象
在之前的教程中(34 圖解:靜態(tài)類型與動態(tài)類型),我使用圖解,詳細的解釋了 Go 語言中的靜態(tài)類型與動態(tài)類型。
其中有一個非常重要的知識點,就是如下這種定義變量的方法
package?main
import?"fmt"
func?main()?{
????age?:=?(int)(25)
????//?等價于?age?:=?25
????fmt.Printf("type:?%T,?data:?%v?",?age,?age)
????//?output:?type:?int,?data:?25
}
思路變通一下,這個知識點,也可以應用于類型的轉換。
package?main
import?"fmt"
func?main()?{
????var?a?int8?=?5
????fmt.Printf("%T?\n",?a)
????//?output:?int8
????b?:=?(int16)(a)
????fmt.Printf("%T?\n",?b)
????//?output:?int16
}
以上,就是我總結的四種類型轉換方法,如果你有更多的原生類型轉換方法,歡迎后臺留言告訴我。
? ?

???
