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

Go語言之再談空接口

開發(fā) 后端
Go編譯器可以把任何類型的數(shù)據(jù)封裝成該結(jié)構(gòu)的對(duì)象;結(jié)果是在語法層面, interface{} 類型的變量可以引用任何類型的數(shù)據(jù), interface{} 類型的形式參數(shù)可以接收任何類型的實(shí)際參數(shù)。

[[430589]]

前言

在 【Go】?jī)?nèi)存中的空接口 一文中,我們知道 interface{} 類型的對(duì)象的結(jié)構(gòu)如下:

  1. // emptyInterface is the header for an interface{} value. 
  2. type emptyInterface struct { 
  3.   typ  *rtype 
  4.   word unsafe.Pointer 

該結(jié)構(gòu)體包含兩個(gè)指針,占 16 個(gè)字節(jié)。

該結(jié)構(gòu)體包含類型信息和數(shù)據(jù)信息,Go編譯器可以把任何類型的數(shù)據(jù)封裝成該結(jié)構(gòu)的對(duì)象;結(jié)果是在語法層面, interface{} 類型的變量可以引用任何類型的數(shù)據(jù), interface{} 類型的形式參數(shù)可以接收任何類型的實(shí)際參數(shù)。

前文只是介紹了 interface{} 的對(duì)象結(jié)構(gòu),但還沒有介紹 interface{} 的類型信息。本文將詳細(xì)分析空接口的類型信息。

繼續(xù)閱讀文本之前,強(qiáng)烈推薦優(yōu)先閱讀以下兩篇圖文:

  • 【Go】?jī)?nèi)存中的空接口
  • 【Go】深入理解函數(shù)

環(huán)境

  1. OS : Ubuntu 20.04.2 LTS; x86_64 
  2. Go : go version go1.16.2 linux/amd64 

聲明

操作系統(tǒng)、處理器架構(gòu)、Go版本不同,均有可能造成相同的源碼編譯后運(yùn)行時(shí)的寄存器值、內(nèi)存地址、數(shù)據(jù)結(jié)構(gòu)等存在差異。

本文僅包含 64 位系統(tǒng)架構(gòu)下的 64 位可執(zhí)行程序的研究分析。

本文僅保證學(xué)習(xí)過程中的分析數(shù)據(jù)在當(dāng)前環(huán)境下的準(zhǔn)確有效性。

代碼清單

  1. package main 
  2.  
  3. import "fmt" 
  4. import "reflect" 
  5.  
  6. func main() { 
  7.   Typeof(Typeof) 
  8.  
  9. //go:noinline 
  10. func Typeof(i interface{}) { 
  11.   t := reflect.TypeOf(i) 
  12.   fmt.Println("函數(shù)類型", t.String()) 
  13.   fmt.Println("參數(shù)類型", t.In(0).String()) 

運(yùn)行結(jié)果

接口類型

接口類型信息的結(jié)構(gòu)定義在reflect/type.go源文件中:

  1. // interfaceType represents an interface type. 
  2. type interfaceType struct { 
  3.   rtype 
  4.   pkgPath name      // import path 
  5.   methods []imethod // sorted by hash 

該結(jié)構(gòu)體占 80 個(gè)字節(jié)。

結(jié)構(gòu)分布圖

將接口類型信息繪制成圖表如下:

內(nèi)存分析

再次強(qiáng)調(diào),繼續(xù)之前務(wù)必閱讀 【Go】?jī)?nèi)存中的函數(shù) ,方便了解本文分析過程。

定義Typeof函數(shù)的目的是方便定位 interface{} 的類型信息,直接在該函數(shù)入口處設(shè)置斷點(diǎn)。

在調(diào)試過程中,首先得到的是Typeof函數(shù)的類型信息。該函數(shù)只有一個(gè)參數(shù),參數(shù)的類型信息位于內(nèi)存地址 0x4a5200 處,這就是空接口的類型信息。

將空接口的類型信息做成圖表如下:

  • rtype.size = 16
  • rtype.ptrdata = 16
  • rtype.hash = 0x18a057e7
  • rtype.tflag = 2 = reflect.tflagExtraStar
  • rtype.align = 8
  • rtype.fieldAlign = 8
  • rtype.kind = 20 = reflect.Interface
  • rtype.equal = 0x4c2ba8 = runtime.nilinterequal
  • rtype.str = 0x000030b0 => *interface {}
  • rtype.ptrToThis = 0x000067c0
  • interfaceType.pkgPath = 0 = nil
  • interfaceType.methods.Data = 0x4a5220
  • interfaceType.methods.Len = 0
  • interfaceType.methods.Cap = 0

從以上數(shù)據(jù)我們可以知道,interface{} 類型的對(duì)象 16 字節(jié)大小、8 字節(jié)對(duì)齊、具有可比較性,沒有任何方法。

ptrToThis = 0x000067c0 是空接口指針類型(*interface{})信息的內(nèi)存偏移量。

空接口是Go語言內(nèi)置的數(shù)據(jù)類型,不屬于任何包,所以包路徑值為空(pkgPath)。

可比較性

空接口具有可比較性。

空接口類型的equal函數(shù)為runtime.nilinterequal,該函數(shù)定義在runtime/alg.go源文件中:

  1. func nilinterequal(p, q unsafe.Pointer) bool { 
  2.   x := *(*eface)(p) 
  3.   y := *(*eface)(q) 
  4.   return x._type == y._type && efaceeq(x._type, x.data, y.data) 
  5.  
  6. func efaceeq(t *_type, x, y unsafe.Pointer) bool { 
  7.   if t == nil { 
  8.     return true 
  9.   } 
  10.   eq := t.equal 
  11.   if eq == nil { 
  12.     panic(errorString("comparing uncomparable type " + t.string())) 
  13.   } 
  14.   if isDirectIface(t) { 
  15.     return x == y 
  16.   } 
  17.   return eq(x, y) 
  18. // isDirectIface reports whether t is stored directly in an interface value. 
  19. func isDirectIface(t *_type) bool { 
  20.   return t.kind&kindDirectIface != 0 

通過源碼,看到空接口對(duì)象比較的邏輯如下:

  1. 如果兩個(gè)對(duì)象的類型不一樣,返回 false
  2. 如果兩個(gè)對(duì)象的類型一樣,并且值為nil,返回 true
  3. 如果兩個(gè)對(duì)象的類型一樣,但是不可比較,直接 panic
  4. 然后進(jìn)行比較,并返回比較結(jié)果。

也就是說,空接口對(duì)象的比較,實(shí)際是其表示的類型和其指向的數(shù)據(jù)的比較。

通過內(nèi)存中的空接口和本文,基本已經(jīng)全面了解了 interface{}。

本文轉(zhuǎn)載自微信公眾號(hào)「Golang In Memory」

 

責(zé)任編輯:姜華 來源: Golang In Memory
相關(guān)推薦

2021-10-03 22:18:14

Go語言整數(shù)

2020-12-31 09:06:44

Go語言Reflect

2021-10-16 17:53:35

Go函數(shù)編程

2021-10-09 07:52:01

Go程序重命名

2022-03-28 13:34:26

Go泛型部署泛型

2019-01-03 09:45:20

Go 前端 Web

2024-01-05 20:46:14

2013-08-20 10:11:20

Go系統(tǒng)管理員

2021-05-12 08:53:54

Go語言調(diào)度

2021-10-18 10:53:26

Go 代碼技術(shù)

2024-01-08 08:23:07

Go語言代碼

2013-07-10 11:11:05

PythonGo語言

2012-08-13 14:13:46

2017-06-14 09:37:05

R語言Apriori算法

2018-08-01 15:10:02

GolangPython語言

2012-02-13 10:03:31

編程開發(fā)

2013-02-19 09:26:17

2018-03-12 22:13:46

GO語言編程軟件

2010-01-14 10:34:02

C++語言

2022-08-15 23:09:53

jsonGo語言
點(diǎn)贊
收藏

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