自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Go 面試題:Go interface 的一個 “坑” 及原理分析

開發(fā) 后端
前幾天在讀者交流群里看到一位小伙伴,針對 interface 的使用有了比較大的疑惑。Go interface 是 Go 語言中最常用的類型之一,大家用慣了 if err != nil 就很容易順手就踩進去了。

 [[387825]]

本文轉(zhuǎn)載自微信公眾號「腦子進煎魚了」,作者陳煎魚。轉(zhuǎn)載本文請聯(lián)系腦子進煎魚了公眾號。

大家好,我是煎魚。

前幾天在讀者交流群里看到一位小伙伴,針對 interface 的使用有了比較大的疑惑。

無獨有偶,我也在網(wǎng)上看到有小伙伴在 Go 面試的時候被問到了:

來自網(wǎng)上博客的截圖

今天特意分享出來讓大家避開這個坑。

例子一

第一個例子,如下代碼:

  1. func main() { 
  2.     var v interface{} 
  3.     v = (*int)(nil) 
  4.     fmt.Println(v == nil) 

你覺得輸出結(jié)果是什么呢?

答案是:

  1. false 

為什么不是 true。明明都已經(jīng)強行置為 nil 了。是不是 Go 編譯器有問題?

例子二

第二個例子,如下代碼:

  1. func main() { 
  2.     var data *byte 
  3.     var in interface{} 
  4.  
  5.     fmt.Println(data, data == nil) 
  6.     fmt.Println(inin == nil) 
  7.  
  8.     in = data 
  9.     fmt.Println(inin == nil) 

你覺得輸出結(jié)果是什么呢?

答案是:

  1. <nil> true 
  2. <nil> true 
  3. <nil> false 

這可就更奇怪了,為什么剛剛聲明出來的 data 和 in 變量,確實是輸出結(jié)果是 nil,判斷結(jié)果也是 true。

怎么把變量 data 一賦予給變量 in,世界就變了?輸出結(jié)果依然是 nil,但判定卻變成了 false。

和上面的第一個例子結(jié)果類似,真是神奇。

原因

interface 判斷與想象中不一樣的根本原因是,interface 并不是一個指針類型,雖然他看起來很像,以至于誤導(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):

  1. type eface struct { 
  2.     _type *_type 
  3.     data  unsafe.Pointer 
  4.  
  5. type iface struct { 
  6.     tab  *itab 
  7.     data unsafe.Pointer 

你會發(fā)現(xiàn) interface 不是單純的值,而是分為類型和值。

所以傳統(tǒng)認(rèn)知的此 nil 并非彼 nil,必須得類型和值同時都為 nil 的情況下,interface 的 nil 判斷才會為 true。

解決辦法

與其說是解決方法,不如說是委婉的破局之道。在不改變類型的情況下,方法之一是利用反射(reflect),如下代碼:

  1. func main() { 
  2.     var data *byte 
  3.     var in interface{} 
  4.  
  5.     in = data 
  6.     fmt.Println(IsNil(in)) 
  7.  
  8. func IsNil(i interface{}) bool { 
  9.     vi := reflect.ValueOf(i) 
  10.     if vi.Kind() == reflect.Ptr { 
  11.         return vi.IsNil() 
  12.     } 
  13.     return false 

利用反射來做 nil 的值判斷,在反射中會有針對 interface 類型的特殊處理,最終輸出結(jié)果是:true,達(dá)到效果。

其他方法的話,就是改變原有的程序邏輯,例如:

  • 對值進行 nil 判斷,再返回給 interface 設(shè)置。
  • 返回具體的值類型,而不是返回 interface。

總結(jié)

Go interface 是 Go 語言中最常用的類型之一,大家用慣了 if err != nil 就很容易順手就踩進去了。

 

責(zé)任編輯:武曉燕 來源: 腦子進煎魚了
相關(guān)推薦

2023-07-14 08:12:21

計時器unsafecontext

2023-06-20 08:25:53

NESTED源碼mybatis

2023-07-28 08:04:56

StringHeaatomic線程

2012-08-02 09:36:58

fork面試題

2011-07-18 15:08:19

SQL存儲過程

2015-10-12 15:50:07

PaaS云平臺開發(fā)go

2021-03-05 08:51:00

Go語言make

2024-08-14 13:24:24

2011-08-17 10:28:53

多對多查詢SQL Server

2021-12-15 10:54:12

Gogofmt命令Go源代碼

2021-07-04 08:01:30

Synchronize線程安全并發(fā)編程

2009-06-06 18:34:05

java面試題

2023-05-10 08:05:41

GoWeb應(yīng)用

2023-02-26 01:37:57

goORM代碼

2013-09-10 14:50:12

數(shù)組面試題

2014-12-02 10:02:30

2011-05-19 16:30:38

軟件測試

2009-06-16 13:41:19

Hibernate面試Hibernate面試

2025-03-12 08:00:00

單點登錄單設(shè)備登錄程序

2013-11-01 09:27:48

Twitter技術(shù)面試
點贊
收藏

51CTO技術(shù)棧公眾號