深入源码分析go类型系统
来源:互联网 发布:新股自动申购软件 编辑:程序博客网 时间:2024/05/21 10:42
深入源码分析go类型系统
Ø runtime/type.h
go类型描述的静态信息
//type go类型最通用定义,go的类型系统通过这个数据结构来进行驱动
//Type是类型信息结构体中公共的部分
20 struct Type
21 {
22 uintptr size; //类型大小
23 uint32 hash; //hash值
24 uint8 _unused;
25 uint8 align; //对齐
26 uint8 fieldAlign; //field对齐
27 uint8 kind; //reflect包中的Kind类型就是这个,它是个类型的枚举值
28 Alg *alg;
29 void *gc; //垃圾回收相关
30 String *string;
31 UncommonType *x; //指向指针,该指针指向的struct 中包含该类型实现的函数指针数组
32 Type *ptrto;
33 byte *zero; // ptr to the zero value for this type
34 };
// 非接口类型method描述数据结构
36 struct Method
37 {
38 String *name;
39 String *pkgPath;
40 Type *mtyp;
41 Type *typ;
42 void (*ifn)(void);
43 void (*tfn)(void);
44 };
45
//具体类型的methods集合
46 struct UncommonType
47 {
48 String *name;
49 String *pkgPath;
50 Slice mhdr;
51 Method m[];
52 };
//有methods 的interface 编译器构造的静态数据结构
54 struct IMethod
55 {
56 String *name;
57 String *pkgPath;
58 Type *type;
59 };
60
61 struct InterfaceType
62 {
63 Type;
64 Slice mhdr;
65 IMethod m[];
66 };
// 空接口interface{}
编译器不会为该种类型构造一个静态数据结构
空接口在赋值后才有意义,单单声明个空接口是没有意义的
Ø runtime/type.h
//接口赋值时编译器构造的动态数据结构
//其他类型赋值给interfac{},编译器动态构造的数据结构
189 struct Eface
190 {
191 Type* type; //指向具体类型
192 void* data; //类型变量的值
193 };
//其他类型赋值给非空接口,编译器构造的数据结构
184 struct Iface
185 {
186 Itab* tab; //接口动态赋值时数据结构
187 void* data; //类型值
188 };
// 具体类型变量赋值给非空接口类型变量时,编译器构造的数据结构
472 struct Itab
473 {
474 InterfaceType* inter; //指向接口静态类型描述,见上文InterfaceType结构
475 Type* type; //指向结构被赋值的具体变量的类型描述
476 Itab* link;
477 int32 bad;
478 int32 unused;
479 void (*fun[])(void); //拷贝具体类型变量的函数指针到该数组
480 };
l 接口是可被实例化的类型,不仅是语言上的约束规范;当我们创建接变量时,将会为其分配部分内存空间(此时接口没有任何价值,不能使用);当将type实例赋值时给接口变量时才分配全部空间(包括实例变量值或指针的拷贝)和初始化全部数据结构。单单声明一个接口变量,而不对其赋值,是没有意义的。
$GOROOT/src/pkg/runtime/runtime.h
178 struct Iface
179 {
180 Itab* tab;
181 void* data;
182 };
449 struct Itab
450 {
451 InterfaceType* inter;
452 Type* type;
453 Itab* link;
454 int32 bad;
455 int32 unused;
456 void (*fun[])(void);
457 };
上个例子中:
var m Tester 仅仅创建Iface 数据结构,但是 Itab 和 void * data 都没有赋值(nil),此时变量m 没有任何意义,使用m 会引发运行时panic
(对m进行反射TypeOf 返回nil)
(对m进行反射ValueOf 返回空的value,调用其方法会引发panic)
只有给m 赋值一个type 实例变量,才会初始化Itab 和 void * data,接口变量才能真的使用
接口变量是用来赋值的,单单声明一个接口变量而不赋值违背了接口设计原则;
接口是用来结构的,接口变量一定要实例化(被赋值);
接口变量可以赋值给另一个接口变量;
反射包是对go类型的更深一个层次抽象,其与go底层数据结构的映射关系如下:
描述类型的数据结构
描述类型变量存储结构的数据结构
runtime/type.h
runtime/runtime.h
reflect/type.go
reflect/value.go
Type结构
类型信息是静态的,声明一种新类型,编译器只需生成一个该类型的数据结构描述即可;
类型变量是动态的,new或者直接声明一个变量,都要为该变量分配存储空间,同时将该变量与类型信息关联;以便在调用类型方法的时候能够找到正确的入口地址和参数;
编译器在编译时即已经确定类型信息和类型方法,在运行时将参数值和调用类型方法绑定,完成方法调用;
go大部分类型检查是在编译器进行的(包括接口赋值),有两个例外是在运行期进行的:
1> 调用反射的方法
2> 接口的查询 t.(TYPE)
接口操作
语法
时间点
类型变量赋值给接口
var i InterfaceA = &structA{}
编译期间
接口查询
var i InterfaceA = &structA{}
v, ok := i.(TypeB)
运行期间
接口变量赋值给接口变量
var rw IReadWriter = ...
var r IReader = rw
编译期间
数据结构
runtime/type.h
reflect/type.go
type
20 struct Type
21 {
22 uintptr size;
23 uint32 hash;
24 uint8 _unused;
25 uint8 align;
26 uint8 fieldAlign;
27 uint8 kind;
28 Alg *alg;
29 void *gc;
30 String *string;
31 UncommonType *x;
32 Type *ptrto;
33 byte *zero; // ptr to the zero value for this type
34 };
244 type rtype struct {
245 size uintptr // size in bytes
246 hash uint32 // hash of type; avoids computation in hash tables
247 _ uint8 // unused/padding
248 align uint8 // alignment of variable with this type
249 fieldAlign uint8 // alignment of struct field with this type
250 kind uint8 // enumeration for C
251 alg *uintptr // algorithm table (../runtime/runtime.h:/Alg)
252 gc unsafe.Pointer // garbage collection data
253 string *string // string form; unnecessary but undeniably useful
254 *uncommonType // (relatively) uncommon fields
255 ptrToThis *rtype
// type for pointer to this type, if used in binary or has methods
256 zero unsafe.Pointer // pointer to zero value
257 }
UncommonType
非接口类型静态数据结构
36 struct Method
37 {
38 String *name;
39 String *pkgPath;
40 Type *mtyp;
41 Type *typ;
42 void (*ifn)(void);
43 void (*tfn)(void);
44 };
45
46 struct UncommonType
47 {
48 String *name;
49 String *pkgPath;
50 Slice mhdr;
51 Method m[];
52 };
260 type method struct {
261 name *string // name of method
262 pkgPath *string // nil for exported Names; otherwise import path
263 mtyp *rtype // method type (without receiver)
264 typ *rtype // .(*FuncType) underneath (with receiver)
265 ifn unsafe.Pointer // fn used in interface call (one-word receiver)
266 tfn unsafe.Pointer // fn used for normal method call
267 }
273 type uncommonType struct {
274 name *string // name of type
275 pkgPath *string // import path; nil for built-in types like int, string
276 methods []method // methods associated with type
277 }
InterfaceType
非空接口类型数据结构
54 struct IMethod
55 {
56 String *name;
57 String *pkgPath;
58 Type *type;
59 };
60
61 struct InterfaceType
62 {
63 Type;
64 Slice mhdr;
65 IMethod m[];
66 };
311 // imethod represents a method on an interface type
312 type imethod struct {
313 name *string // name of method
314 pkgPath *string // nil for exported Names; otherwise import path
315 typ *rtype // .(*FuncType) underneath
316 }
317
318 // interfaceType represents an interface type.
319 type interfaceType struct {
320 rtype `reflect:"interface"`
321 methods []imethod // sorted by hash
322 }
内置数据类型
68 struct MapType
69 {
70 Type;
71 Type *key;
72 Type *elem;
73 Type *bucket;
74 Type *hmap;
75 };
77 struct ChanType
78 {
79 Type;
80 Type *elem;
81 uintptr dir;
82 };
84 struct SliceType
85 {
86 Type;
87 Type *elem;
88 };
90 struct FuncType
91 {
92 Type;
93 bool dotdotdot;
94 Slice in;
95 Slice out;
96 }
97
98 struct PtrType
99 {
100 Type;
101 Type *elem;
102 };
325 type mapType struct {
326 rtype `reflect:"map"`
327 key *rtype // map key type
328 elem *rtype // map element (value) type
329 bucket *rtype // internal bucket structure
330 hmap *rtype // internal map header
331 }
296 // chanType represents a channel type.
297 type chanType struct {
298 rtype `reflect:"chan"`
299 elem *rtype // channel element type
300 dir uintptr // channel direction (ChanDir)
301 }
339 // sliceType represents a slice type.
340 type sliceType struct {
341 rtype `reflect:"slice"`
342 elem *rtype // slice element type
343 }
303 // funcType represents a function type.
304 type funcType struct {
305 rtype `reflect:"func"`
306 dotdotdot bool // last input parameter is ...
307 in []*rtype // input parameter types
308 out []*rtype // output parameter types
309 }
333 // ptrType represents a pointer type.
334 type ptrType struct {
335 rtype `reflect:"ptr"`
336 elem *rtype // pointer element (pointed at) type
337 }
289 type arrayType struct {
290 rtype `reflect:"array"`
291 elem *rtype // array element type
292 slice *rtype // slice type
293 len uintptr
294 }
345 // Struct field
346 type structField struct {
347 name *string // nil for embedded fields
348 pkgPath *string // nil for exported Names; otherwise import path
349 typ *rtype // type of field
350 tag *string // nil if no tag
351 offset uintptr // byte offset of field within struct
352 }
353
354 // structType represents a struct type.
355 type structType struct {
356 rtype `reflect:"struct"`
357 fields []structField // sorted by offset
358 }
go支持类型系统
struct 类型比较特殊,他是一种符合类型
函数也是一等公民,也是一种基础类型
210 const (
211 Invalid Kind = iota
212 Bool
213 Int
214 Int8
215 Int16
216 Int32
217 Int64
218 Uint
219 Uint8
220 Uint16
221 Uint32
222 Uint64
223 Uintptr
224 Float32
225 Float64
226 Complex64
227 Complex128
228 Array
229 Chan
230 Func
231 Interface
232 Map
233 Ptr
234 Slice
235 String
236 Struct
237 UnsafePointer
238 )
Value具体映射关系
value 主要是描述类型变量的内存布局
接口是个粘合剂,go在编译时也准备一些数据结构来辅助变量间的运算
数据结构
runtime/runtime.h
reflect/value.go
空接口
//空接口
189 struct Eface
190 {
191 Type* type;
192 void* data;
193 };
//空接口
278 // emptyInterface is the header for an interface{} value.
279 type emptyInterface struct {
280 typ *rtype
281 word iword
282 }
283
非空接口
//非空接口数据描述
184 struct Iface
185 {
186 Itab* tab;
187 void* data;
188 };
470 // layout of Itab known to compilers
471 // allocated in non-garbage-collected memory
472 struct Itab
473 {
474 InterfaceType* inter;
475 Type* type;
476 Itab* link;
477 int32 bad;
478 int32 unused;
479 void (*fun[])(void);
480 };
////非空接口数据描述
284 // nonEmptyInterface is the header for a interface value with methods.
285 type nonEmptyInterface struct {
286 // see ../runtime/iface.c:/Itab
287 itab *struct {
288 ityp *rtype // static interface type
289 typ *rtype // dynamic concrete type
290 link unsafe.Pointer
291 bad int32
292 unused int32
293 fun [100000]unsafe.Pointer
// method table
294 }
295 word iword
296 }
内置数据类型存储模型
205 struct Slice
206 {
207 byte* array;
208 uintgo len;
209 uintgo cap;
210 };
174 struct String
175 {
176 byte* str;
177 intgo len;
178 };
194 struct Complex64
195 {
196 float32 real;
197 float32 imag;
198 };
199 struct Complex128
200 {
201 float64 real;
202 float64 imag;
203 };
1931 type SliceHeader struct {
1932 Data uintptr
1933 Len int
1934 Cap int
1935 }
1914 type StringHeader struct {
1915 Data uintptr
1916 Len int
1917 }
Layout of in-memory per-function information prepared by linker
由连接器在内存中位每个函数分配的信息
455 struct Func
456 {
457 uintptr entry; // start pc
458 int32 nameoff;// function name
459
460 int32 args; // in/out args size
461 int32 frame; // legacy frame size; use pcsp if possible
462
463 int32 pcsp;
464 int32 pcfile;
465 int32 pcln;
466 int32 npcdata;
467 int32 nfuncdata;
468 };
- 深入源码分析go类型系统
- go-restful实战与深入分析之源码篇
- postgresql源码分析--解析sql--类型系统
- go 类型系统(二)
- nsq源码分析backend_queue.go
- 深入JAVA源码分析
- spymemcached源码深入分析
- 深入分析HaspMap源码
- 深入源码分析HashSet
- 深入分析HaspMap源码
- 深入源码分析HashSet
- okhttp3 源码深入分析
- FutureTask源码深入分析
- Buffer源码深入分析
- Lua 5.3 源码分析(一)类型系统
- 5. Go 语言的类型系统(Go Tutorial)
- Go面向对象编程之系统类型
- go database/sql 源码分析 -题外篇
- HDU1879 继续畅通工程
- KMP字符串匹配算法
- mysql常用函数汇总
- java日志组件介绍(common-logging,log4j,slf4j,logback )+ java日志,需要知道的几件事(commons-logging,log4j,slf4j,logback
- Android Studio中Git的安装配置以及使用
- 深入源码分析go类型系统
- HTML5之FileReader的使用
- LBP描述算子简介
- 4种CSS3超酷移动手机滑动隐藏侧边栏菜单特效
- MYSQL打开的文件数量太多
- poj-2752-Seek the Name, Seek the Fame
- Java Servlet 开发常用代码、模板、问题
- 某杀毒软件的crash dump 分析
- JSTL c标签和Struts2 s标签常用功能对比