新聞中心
[[387825]]

創(chuàng)新互聯(lián)建站于2013年開始,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢想脫穎而出為使命,1280元建甌做網(wǎng)站,已為上家服務(wù),為建甌各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:028-86922220
本文轉(zhuǎn)載自微信公眾號(hào)「腦子進(jìn)煎魚了」,作者陳煎魚。轉(zhuǎn)載本文請聯(lián)系腦子進(jìn)煎魚了公眾號(hào)。
大家好,我是煎魚。
前幾天在讀者交流群里看到一位小伙伴,針對 interface 的使用有了比較大的疑惑。
無獨(dú)有偶,我也在網(wǎng)上看到有小伙伴在 Go 面試的時(shí)候被問到了:
來自網(wǎng)上博客的截圖
今天特意分享出來讓大家避開這個(gè)坑。
例子一
第一個(gè)例子,如下代碼:
- func main() {
- var v interface{}
- v = (*int)(nil)
- fmt.Println(v == nil)
- }
你覺得輸出結(jié)果是什么呢?
答案是:
- false
為什么不是 true。明明都已經(jīng)強(qiáng)行置為 nil 了。是不是 Go 編譯器有問題?
例子二
第二個(gè)例子,如下代碼:
- func main() {
- var data *byte
- var in interface{}
- fmt.Println(data, data == nil)
- fmt.Println(in, in == nil)
- in = data
- fmt.Println(in, in == nil)
- }
你覺得輸出結(jié)果是什么呢?
答案是:
true true false
這可就更奇怪了,為什么剛剛聲明出來的 data 和 in 變量,確實(shí)是輸出結(jié)果是 nil,判斷結(jié)果也是 true。
怎么把變量 data 一賦予給變量 in,世界就變了?輸出結(jié)果依然是 nil,但判定卻變成了 false。
和上面的第一個(gè)例子結(jié)果類似,真是神奇。
原因
interface 判斷與想象中不一樣的根本原因是,interface 并不是一個(gè)指針類型,雖然他看起來很像,以至于誤導(dǎo)了不少人。
我們鉆下去 interface,interface 共有兩類數(shù)據(jù)結(jié)構(gòu):
- runtime.eface 結(jié)構(gòu)體:表示不包含任何方法的空接口,也稱為 empty interface。
- runtime.iface 結(jié)構(gòu)體:表示包含方法的接口。
看看這兩者相應(yīng)的底層數(shù)據(jù)結(jié)構(gòu):
- type eface struct {
- _type *_type
- data unsafe.Pointer
- }
- type iface struct {
- tab *itab
- data unsafe.Pointer
- }
你會(huì)發(fā)現(xiàn) interface 不是單純的值,而是分為類型和值。
所以傳統(tǒng)認(rèn)知的此 nil 并非彼 nil,必須得類型和值同時(shí)都為 nil 的情況下,interface 的 nil 判斷才會(huì)為 true。
解決辦法
與其說是解決方法,不如說是委婉的破局之道。在不改變類型的情況下,方法之一是利用反射(reflect),如下代碼:
- func main() {
- var data *byte
- var in interface{}
- in = data
- fmt.Println(IsNil(in))
- }
- func IsNil(i interface{}) bool {
- vi := reflect.ValueOf(i)
- if vi.Kind() == reflect.Ptr {
- return vi.IsNil()
- }
- return false
- }
利用反射來做 nil 的值判斷,在反射中會(huì)有針對 interface 類型的特殊處理,最終輸出結(jié)果是:true,達(dá)到效果。
其他方法的話,就是改變原有的程序邏輯,例如:
- 對值進(jìn)行 nil 判斷,再返回給 interface 設(shè)置。
- 返回具體的值類型,而不是返回 interface。
總結(jié)
Go interface 是 Go 語言中最常用的類型之一,大家用慣了 if err != nil 就很容易順手就踩進(jìn)去了。
文章標(biāo)題:Go面試題:Gointerface的一個(gè)“坑”及原理分析
當(dāng)前鏈接:http://m.fisionsoft.com.cn/article/cciioso.html


咨詢
建站咨詢
