Golang斷言判斷值類型的實(shí)現(xiàn)方法
Golang可以通過(guò)斷言,判斷值的類型
s:="hello world"
i:=interface{}(s)//將數(shù)值轉(zhuǎn)化為interface空接口類型
//需要注意的是,必須是空接口類型才能使用斷言,如果不是空接口類型會(huì)報(bào)錯(cuò)
//Invalid type assertion: a.(string) (non-interface type string on left)
v,e:=i.(string)//返回value和error值,當(dāng)err值為true則轉(zhuǎn)化成功,value的值為括號(hào)中的值類型,當(dāng)err值為false,則轉(zhuǎn)化不成功
也可以通過(guò)反射判斷值的類型
name:="test" t:=relfect.TypeOf(name) fmt.Println(t)//通過(guò)反射確定值的類型
類型斷言是什么,類型斷言和類型轉(zhuǎn)換有什么區(qū)別,這個(gè)問(wèn)題以前我也常常分不清楚。為了幫助和我有一樣疑問(wèn)的人,我決定得寫(xiě)一篇關(guān)于這方面的博文,介紹一下golang中的類型斷言和類型轉(zhuǎn)換的區(qū)別,在JavaScript的超集Typescript里,也同樣有類型斷言的概念。這篇簡(jiǎn)短的博文就是幫助大家解答這個(gè)疑問(wèn),我會(huì)盡量短的說(shuō)清楚,我理解的類型轉(zhuǎn)換和類型斷言的區(qū)別是什么。
什么是類型轉(zhuǎn)換
類型轉(zhuǎn)換在很多靜態(tài)類型的語(yǔ)言中都會(huì)有的概念,類型轉(zhuǎn)換通常分為顯示類型轉(zhuǎn)換和隱式類型轉(zhuǎn)換。強(qiáng)制類型轉(zhuǎn)換形如:
f := 11.22 i := int(f)
例如有個(gè)float32的變量被賦值為11.22,現(xiàn)在我們想去掉小數(shù)部分,最簡(jiǎn)單的方法就是將float32轉(zhuǎn)換為int32。
簡(jiǎn)單來(lái)說(shuō),強(qiáng)制類型轉(zhuǎn)換就是你要從一個(gè)類型強(qiáng)制轉(zhuǎn)換到另一個(gè)類型。適用于一些基本類型,比如int, float之類等等。但在golang中,類型匹配是相當(dāng)嚴(yán)格的,很多時(shí)候編譯器不會(huì)幫你去做,所以大多數(shù)的情況下,我們還是會(huì)做一些顯示的類型轉(zhuǎn)換。
比如這段看起來(lái)在其它靜態(tài)類型語(yǔ)言中毫無(wú)問(wèn)題的代碼片段,在golang中編譯期就會(huì)報(bào)錯(cuò),golang會(huì)強(qiáng)制讓你做類型轉(zhuǎn)換。
var i int = 1 var f float64 = i
接下來(lái)看看隱式的類型轉(zhuǎn)換。golang中的隱式類型轉(zhuǎn)換主要存在于運(yùn)行時(shí)。比如:
var w io.Writer = os.Stdout
這里將*File類型賦值給了io.Writer類型,在運(yùn)行時(shí)會(huì)做一個(gè)隱式的類型轉(zhuǎn)換。
什么是斷言
在了解什么是類型斷言之前,先來(lái)了解一下斷言是什么

這是尼克楊嗎?
是
簡(jiǎn)而言之,斷言就是對(duì)一種條件進(jìn)行假設(shè),如果這是尼克楊,那么我要要干嘛?如果這不是尼克楊又怎樣?
隨之,類型斷言就是對(duì)類型進(jìn)行一種假設(shè)。
這里拿Typescript來(lái)說(shuō)個(gè)事,在TS里我們很多時(shí)候會(huì)用到一種類型叫聯(lián)合類型,聯(lián)合類型A | B可以理解為它可以是A類型或者是B類型。實(shí)際例子:
let zhangsan:Student | null //表示zhangsan是一個(gè)Student或者null類型
我們需要使用zhangsan的時(shí)候,可以使用類型斷言
if(zhangsan) zs = <Student>zhangsan //或者 if(zhangsan) zs = zhangsan as Student
在golang中的類型斷言和Typescript中的第二種類型斷言比較相像。在golang中形如
x.(T)
x是一種接口類型,T可以是一種具體的類型也可以是一種接口類型
golang為什么需要類型斷言
為此,我們思考一個(gè)問(wèn)題,為什么Golang需要類型斷言,golang中對(duì)類型的要求十分嚴(yán)格,而且golang中也沒(méi)有Typescript中的聯(lián)合類型,好像一切類型都是固定不變的,有了強(qiáng)制轉(zhuǎn)換類型,為什么還需要類型斷言呢?
在Golang中,接口類型是能夠隱式轉(zhuǎn)換的??匆粋€(gè)具體的例子:
var w io.Writer = os.Stdout
w的類型為io.Writer,但是它被賦值了*File,這是Golang幫助我們做了一次類型轉(zhuǎn)換。這次類型轉(zhuǎn)換是在運(yùn)行時(shí)的,編譯時(shí)并不能確定下來(lái)。在運(yùn)行時(shí),這個(gè)接口值的類型被賦值為了*File,與此同時(shí),值也被賦值為了os.Stdout。
上述說(shuō)明了一個(gè)問(wèn)題,接口值的類型是不固定的!因?yàn)樗念愋褪且谶\(yùn)行時(shí)才能確定下來(lái),這需要看它的動(dòng)態(tài)值的類型才能確定。這就是需要類型斷言的原因了。
再看一個(gè)具體的例子
var w io.Writer = os.Stdout
這條語(yǔ)句執(zhí)行過(guò)后,w只會(huì)擁有write方法,但是原本的*File不止擁有write方法,應(yīng)該還擁有read方法,同時(shí),它也是io.ReadWriter接口的一個(gè)實(shí)例。如果這時(shí)候我們想使用read方法怎么辦,那就需要類型斷言了。
rw := w.(io.ReadWriter)
這里將w斷言為ReadWriter類型。斷言類型為一個(gè)接口。暴露了*File的read和write方法
類型斷言的檢查機(jī)制是怎樣的
于是我們想了解Golang的類型斷言的檢查機(jī)制是怎樣的,換句話說(shuō),Golang到底是如何來(lái)判斷斷言是否成功的。
首先明確的是x必須為一個(gè)接口類型,而T可以是一個(gè)具體的類型也可以是一個(gè)接口類型。下面我們分情況討論。
1.當(dāng)T為一個(gè)接口類型時(shí)
當(dāng)T為一個(gè)接口時(shí),首先會(huì)判斷x的動(dòng)態(tài)值是否符合T這個(gè)接口,如果符合的話,斷言成功,反之?dāng)嘌允?,斷言失敗時(shí)會(huì)拋出一個(gè)panic異常。但是如果類型斷言出現(xiàn)在一個(gè)預(yù)期有兩個(gè)結(jié)果的賦值操作中,那么斷言失敗不會(huì)拋出panic異常,而是用一個(gè)bool值標(biāo)識(shí)是否斷言成功。
var w io.Writer = os.Stdout b, ok := w.(*bytes.Buffer)
為了健壯性,我們應(yīng)該對(duì)ok返回的結(jié)果進(jìn)行處理。標(biāo)識(shí)是否斷言成功。
var w io.Writer = os.Stdout
if b, ok := w.(*bytes.Buffer);!ok {
fmt.Fprintf(os.Stderr, "斷言失敗")
} else {
//TODO
}
對(duì)一個(gè)接口類型的類型斷言改變了類型的表述方式,改變了可以獲取的方法集合(通常更大),但是它保護(hù)了接口值內(nèi)部的動(dòng)態(tài)類型和值的部分(Go Programing Language)
當(dāng)T為一個(gè)具體類型時(shí)
當(dāng)T為一個(gè)具體類型時(shí),會(huì)先檢查x的動(dòng)態(tài)值的類型是否為T(mén),如果為T(mén)則斷言成功,如果不為T(mén),則斷言失敗。
具體類型的類型斷言從它的操作對(duì)象中獲得具體的值(Go Programing Language)
當(dāng)x為nil
最后再簡(jiǎn)單的說(shuō)一下x為nil的情況,當(dāng)x為nil時(shí),那么不論斷言類型是任何類型,都會(huì)斷言失敗
到此這篇關(guān)于Golang斷言判斷值類型的實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)Golang斷言判斷值類型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go map底層實(shí)現(xiàn)與擴(kuò)容規(guī)則和特性分類詳細(xì)講解
這篇文章主要介紹了Go map底層實(shí)現(xiàn)與擴(kuò)容規(guī)則和特性,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2023-03-03
golang時(shí)間字符串和時(shí)間戳轉(zhuǎn)換的案例
這篇文章主要介紹了golang時(shí)間字符串和時(shí)間戳轉(zhuǎn)換的案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
Go語(yǔ)言常見(jiàn)錯(cuò)誤接口污染解決分析
這篇文章主要為大家介紹了Go語(yǔ)言常見(jiàn)錯(cuò)誤接口污染解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
go語(yǔ)言Pflag Viper Cobra 核心功能使用介紹
這篇文章主要為大家介紹了go語(yǔ)言Pflag Viper Cobra 核心功能使用介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
Go接口構(gòu)建可擴(kuò)展Go應(yīng)用示例詳解
本文深入探討了Go語(yǔ)言中接口的概念和實(shí)際應(yīng)用場(chǎng)景。從基礎(chǔ)知識(shí)如接口的定義和實(shí)現(xiàn),到更復(fù)雜的實(shí)戰(zhàn)應(yīng)用如解耦與抽象、多態(tài)、錯(cuò)誤處理、插件架構(gòu)以及資源管理,文章通過(guò)豐富的代碼示例和詳細(xì)的解釋,展示了Go接口在軟件開(kāi)發(fā)中的強(qiáng)大功能和靈活性2023-10-10
Golang編程實(shí)現(xiàn)刪除字符串中出現(xiàn)次數(shù)最少字符的方法
這篇文章主要介紹了Golang編程實(shí)現(xiàn)刪除字符串中出現(xiàn)次數(shù)最少字符的方法,涉及Go語(yǔ)言字符串遍歷與運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2017-01-01
基于GORM實(shí)現(xiàn)CreateOrUpdate方法詳解
這篇文章主要為大家介紹了基于GORM實(shí)現(xiàn)CreateOrUpdate方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
Golang中基礎(chǔ)的命令行模塊urfave/cli的用法說(shuō)明
這篇文章主要介紹了Golang中基礎(chǔ)的命令行模塊urfave/cli的用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12

