Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // The reflect package implements run-time reflection, allowing a program to | 5 // The reflect package implements run-time reflection, allowing a program to |
6 // manipulate objects with arbitrary types. The typical use is to take a | 6 // manipulate objects with arbitrary types. The typical use is to take a |
7 // value with static type interface{} and extract its dynamic type | 7 // value with static type interface{} and extract its dynamic type |
8 // information by calling Typeof, which returns a Type. | 8 // information by calling Typeof, which returns a Type. |
9 // | 9 // |
10 // A call to NewValue returns a Value representing the run-time data. | 10 // A call to NewValue returns a Value representing the run-time data. |
11 // MakeZero takes a Type and returns a Value representing a zero value | 11 // Zero takes a Type and returns a Value representing a zero value |
12 // for that type. | 12 // for that type. |
13 package reflect | 13 package reflect |
14 | 14 |
15 import ( | 15 import ( |
16 "runtime" | 16 "runtime" |
17 "strconv" | 17 "strconv" |
18 "sync" | 18 "sync" |
19 "unsafe" | 19 "unsafe" |
20 ) | 20 ) |
21 | 21 |
22 /* | |
23 We want to be able to call methods on Type and to compare types for equality. | |
r
2011/04/02 18:45:33
i think this comment can go. at least it needs rep
| |
24 Thus Type must be either an opaque type or an interface. | |
25 If we make it an interface then existing code changes less. | |
26 If we make Type an opaque type then that could allow overwriting | |
27 type data using copying. It also means saying *Type everywhere | |
28 but plain Value (not *Value), which is a bit strange. Let's use | |
29 the interface for better protection and to lose the *. | |
30 | |
31 | |
32 */ | |
33 | |
34 // Type is the representation of a Go type. | 22 // Type is the representation of a Go type. |
r
2011/04/02 18:45:33
might be good to have helper methods or functions
| |
35 // | 23 // |
36 // Not all methods apply to all kinds of types. Restrictions, | 24 // Not all methods apply to all kinds of types. Restrictions, |
37 // if any, are noted in the documentation for each method. | 25 // if any, are noted in the documentation for each method. |
38 // Use the Kind method to find out the kind of type before | 26 // Use the Kind method to find out the kind of type before |
39 // calling kind-specific methods. Calling a method | 27 // calling kind-specific methods. Calling a method |
40 // inappropriate to the kind of type causes a run time panic. | 28 // inappropriate to the kind of type causes a run-time panic. |
r
2011/04/02 18:45:33
s/run time/run-time/ (adjective)
| |
41 type Type interface { | 29 type Type interface { |
42 // Methods applicable to all types. | 30 // Methods applicable to all types. |
43 | 31 |
44 » // Align returns the alignment of a value of this type | 32 » // Align returns the alignment in bytes of a value of |
45 » // when allocated in memory. | 33 » // this type when allocated in memory. |
r
2011/04/02 18:45:33
what units?
| |
46 Align() int | 34 Align() int |
47 | 35 |
48 » // FieldAlign returns the alignment of a value of this type | 36 » // FieldAlign returns the alignment in bytes of a value of |
49 » // when used as a field in a struct. | 37 » // this type when used as a field in a struct. |
r
2011/04/02 18:45:33
what units?
| |
50 FieldAlign() int | 38 FieldAlign() int |
51 | 39 |
52 // Method returns the i'th method in the type's method set. | 40 // Method returns the i'th method in the type's method set. |
r
2011/04/02 18:45:33
what happens if i is out of range?
obviously, it p
| |
41 // It panics if i is not in the range [0, NumMethod()). | |
53 // | 42 // |
54 // For a non-interface type T or *T, the returned Method's Type and Func | 43 // For a non-interface type T or *T, the returned Method's Type and Func |
55 // fields describe a function whose first argument is the receiver. | 44 // fields describe a function whose first argument is the receiver. |
56 // | 45 // |
57 // For an interface type, the returned Method's Type field gives the | 46 // For an interface type, the returned Method's Type field gives the |
58 // method signature, without a receiver, and the Func field is nil. | 47 // method signature, without a receiver, and the Func field is nil. |
59 Method(int) Method | 48 Method(int) Method |
60 | 49 |
61 // NumMethods returns the number of methods in the type's method set. | 50 // NumMethods returns the number of methods in the type's method set. |
62 NumMethod() int | 51 NumMethod() int |
63 | 52 |
64 // Name returns the type's name within its package. | 53 // Name returns the type's name within its package. |
r
2011/04/02 18:45:33
really? i thought it returned pkg.NameOfType
| |
65 // It returns an empty string for unnamed types. | 54 // It returns an empty string for unnamed types. |
66 Name() string | 55 Name() string |
67 | 56 |
68 // PkgPath returns the type's package path. | 57 // PkgPath returns the type's package path. |
69 // The package path is a full package import path like "container/vector ". | 58 // The package path is a full package import path like "container/vector ". |
70 // PkgPath returns an empty string for unnamed types. | 59 // PkgPath returns an empty string for unnamed types. |
71 PkgPath() string | 60 PkgPath() string |
72 | 61 |
73 // Size returns the number of bytes needed to store | 62 // Size returns the number of bytes needed to store |
74 // a value of the given type; it is analogous to unsafe.Sizeof. | 63 // a value of the given type; it is analogous to unsafe.Sizeof. |
75 Size() uintptr | 64 Size() uintptr |
76 | 65 |
77 // String returns a string representation of the type. | 66 // String returns a string representation of the type. |
78 // The string representation may use shortened package names | 67 // The string representation may use shortened package names |
79 // (e.g., vector instead of "container/vector") and is not | 68 // (e.g., vector instead of "container/vector") and is not |
80 // guaranteed to be unique among types. To test for equality, | 69 // guaranteed to be unique among types. To test for equality, |
81 // compare the Types directly. | 70 // compare the Types directly. |
82 String() string | 71 String() string |
83 | 72 |
84 // Kind returns the specific kind of this type. | 73 // Kind returns the specific kind of this type. |
85 Kind() Kind | 74 Kind() Kind |
86 | 75 |
87 // Methods applicable only to some types, depending on Kind. | 76 // Methods applicable only to some types, depending on Kind. |
88 // The methods allowed for each kind are: | 77 // The methods allowed for each kind are: |
89 // | 78 // |
90 // Int*, Uint*, Float*, Complex*: Bits | 79 // Int*, Uint*, Float*, Complex*: Bits |
91 // Array: Elem, Len | 80 // Array: Elem, Len |
92 // Chan: ChanDir, Elem | 81 // Chan: ChanDir, Elem |
93 » //» Func: In, NumIn, Out, NumOut, DotDotDot. | 82 » //» Func: In, NumIn, Out, NumOut, IsVariadic. |
94 // Map: Key, Elem | 83 // Map: Key, Elem |
95 // Ptr: Elem | 84 // Ptr: Elem |
96 // Slice: Elem | 85 // Slice: Elem |
97 // Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumFi eld | 86 // Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumFi eld |
98 | 87 |
99 // Bits returns the size of the type in bits. | 88 // Bits returns the size of the type in bits. |
100 // It panics if the type's Kind is not one of the | 89 // It panics if the type's Kind is not one of the |
101 » // sized or unsized Int, Uint, Float, or Complex knids. | 90 » // sized or unsized Int, Uint, Float, or Complex kinds. |
102 Bits() int | 91 Bits() int |
103 | 92 |
104 // ChanDir returns a channel type's direction. | 93 // ChanDir returns a channel type's direction. |
105 // It panics if the type's Kind is not Chan. | 94 // It panics if the type's Kind is not Chan. |
106 ChanDir() ChanDir | 95 ChanDir() ChanDir |
107 | 96 |
108 » // DotDotDot returns true if a function type's final input parameter | 97 » // IsVariadic returns true if a function type's final input parameter |
109 // is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the paramet er's | 98 // is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the paramet er's |
110 » // underlying static type []T. | 99 » // implicit actual type []T. |
111 // | 100 // |
112 // For concreteness, if t represents func(x int, y ... float), then | 101 // For concreteness, if t represents func(x int, y ... float), then |
113 // | 102 // |
114 // t.NumIn() == 2 | 103 // t.NumIn() == 2 |
115 // t.In(0) is the reflect.Type for "int" | 104 // t.In(0) is the reflect.Type for "int" |
116 // t.In(1) is the reflect.Type for "[]float" | 105 // t.In(1) is the reflect.Type for "[]float" |
117 » //» t.DotDotDot() == true | 106 » //» t.IsVariadic() == true |
118 // | 107 // |
119 » // DotDotDot panics if the type's Kind is not Func. | 108 » // IsVariadic panics if the type's Kind is not Func. |
120 » DotDotDot() bool | 109 » IsVariadic() bool |
r
2011/04/02 18:45:33
wrong name for a boolean method. HasDotDotDot is
| |
121 | 110 |
122 // Elem returns a type's element type. | 111 // Elem returns a type's element type. |
niemeyer
2011/04/04 13:52:35
s/element type/element Type/ ?
rsc
2011/04/05 16:29:45
I intentionally left type lower case in most place
| |
123 // It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice. | 112 // It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice. |
124 Elem() Type | 113 Elem() Type |
125 | 114 |
126 // Field returns a struct type's i'th field. | 115 // Field returns a struct type's i'th field. |
r
2011/04/02 18:45:33
what if i is out of range?
| |
127 // It panics if the type's Kind is not Struct. | 116 // It panics if the type's Kind is not Struct. |
117 // It panics if i is not in the range [0, NumField()). | |
128 Field(i int) StructField | 118 Field(i int) StructField |
129 | 119 |
130 // FieldByIndex returns the nested field corresponding | 120 // FieldByIndex returns the nested field corresponding |
131 // to the index sequence. It is equivalent to calling Field | 121 // to the index sequence. It is equivalent to calling Field |
132 // successively for each index i. | 122 // successively for each index i. |
133 // It panics if the type's Kind is not Struct. | 123 // It panics if the type's Kind is not Struct. |
134 FieldByIndex(index []int) StructField | 124 FieldByIndex(index []int) StructField |
135 | 125 |
136 // FieldByName returns the struct field with the given name | 126 // FieldByName returns the struct field with the given name |
137 // and a boolean indicating if the field was found. | 127 // and a boolean indicating if the field was found. |
138 FieldByName(name string) (StructField, bool) | 128 FieldByName(name string) (StructField, bool) |
139 | 129 |
140 // FieldByNameFunc returns the first struct field with a name | 130 // FieldByNameFunc returns the first struct field with a name |
141 // that satisfies the match function and a boolean indicating if | 131 // that satisfies the match function and a boolean indicating if |
142 // the field was found. | 132 // the field was found. |
143 FieldByNameFunc(match func(string) bool) (StructField, bool) | 133 FieldByNameFunc(match func(string) bool) (StructField, bool) |
144 | 134 |
145 // In returns the type of a function type's i'th input parameter. | 135 // In returns the type of a function type's i'th input parameter. |
146 // It panics if the type's Kind is not Func. | 136 // It panics if the type's Kind is not Func. |
r
2011/04/02 18:45:33
here and for Out: what if i is out of range?
| |
137 // It panics if i is not in the range [0, NumIn()). | |
147 In(i int) Type | 138 In(i int) Type |
148 | 139 |
149 // Key returns a map type's key type. | 140 // Key returns a map type's key type. |
150 // It panics if the type's Kind is not Map. | 141 // It panics if the type's Kind is not Map. |
151 Key() Type | 142 Key() Type |
niemeyer
2011/04/04 13:52:35
Should this be called MapKey, or MapKeys be rename
rsc
2011/04/05 16:29:45
I don't think so. SliceType still uses Elem() to
| |
152 | 143 |
153 // Len returns an array type's length. | 144 // Len returns an array type's length. |
154 // It panics if the type's Kind is not Array. | 145 // It panics if the type's Kind is not Array. |
155 Len() int | 146 Len() int |
156 | 147 |
157 // NumField returns a struct type's field count. | 148 // NumField returns a struct type's field count. |
158 // It panics if the type's Kind is not Struct. | 149 // It panics if the type's Kind is not Struct. |
159 NumField() int | 150 NumField() int |
160 | 151 |
161 // NumIn returns a function type's input parameter count. | 152 // NumIn returns a function type's input parameter count. |
162 // It panics if the type's Kind is not Func. | 153 // It panics if the type's Kind is not Func. |
163 NumIn() int | 154 NumIn() int |
164 | 155 |
165 // NumOut returns a function type's output parameter count. | 156 // NumOut returns a function type's output parameter count. |
166 // It panics if the type's Kind is not Func. | 157 // It panics if the type's Kind is not Func. |
167 NumOut() int | 158 NumOut() int |
168 | 159 |
169 // Out returns the type of a function type's i'th output parameter. | 160 // Out returns the type of a function type's i'th output parameter. |
170 // It panics if the type's Kind is not Func. | 161 // It panics if the type's Kind is not Func. |
162 // It panics if i is not in the range [0, NumOut()). | |
171 Out(i int) Type | 163 Out(i int) Type |
172 | 164 |
173 uncommon() *uncommonType | 165 uncommon() *uncommonType |
174 } | 166 } |
175 | 167 |
176 // A Kind represents the specific kind of type that a Type represents. | 168 // A Kind represents the specific kind of type that a Type represents. |
177 // The zero Kind is not a valid kind. | 169 // The zero Kind is not a valid kind. |
178 type Kind uint8 | 170 type Kind uint8 |
179 | 171 |
180 const ( | 172 const ( |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
483 } | 475 } |
484 | 476 |
485 func (t *commonType) ChanDir() ChanDir { | 477 func (t *commonType) ChanDir() ChanDir { |
486 if t.Kind() != Chan { | 478 if t.Kind() != Chan { |
487 panic("reflect: ChanDir of non-chan type") | 479 panic("reflect: ChanDir of non-chan type") |
488 } | 480 } |
489 tt := (*chanType)(unsafe.Pointer(t)) | 481 tt := (*chanType)(unsafe.Pointer(t)) |
490 return ChanDir(tt.dir) | 482 return ChanDir(tt.dir) |
491 } | 483 } |
492 | 484 |
493 func (t *commonType) DotDotDot() bool { | 485 func (t *commonType) IsVariadic() bool { |
494 if t.Kind() != Func { | 486 if t.Kind() != Func { |
495 » » panic("reflect: DotDotDot of non-func type") | 487 » » panic("reflect: IsVariadic of non-func type") |
496 } | 488 } |
497 tt := (*funcType)(unsafe.Pointer(t)) | 489 tt := (*funcType)(unsafe.Pointer(t)) |
498 return tt.dotdotdot | 490 return tt.dotdotdot |
499 } | 491 } |
500 | 492 |
501 func (t *commonType) Elem() Type { | 493 func (t *commonType) Elem() Type { |
502 switch t.Kind() { | 494 switch t.Kind() { |
503 case Array: | 495 case Array: |
504 tt := (*arrayType)(unsafe.Pointer(t)) | 496 tt := (*arrayType)(unsafe.Pointer(t)) |
505 return toType(tt.elem) | 497 return toType(tt.elem) |
506 case Chan: | 498 case Chan: |
507 tt := (*chanType)(unsafe.Pointer(t)) | 499 tt := (*chanType)(unsafe.Pointer(t)) |
508 return toType(tt.elem) | 500 return toType(tt.elem) |
509 case Map: | 501 case Map: |
510 tt := (*mapType)(unsafe.Pointer(t)) | 502 tt := (*mapType)(unsafe.Pointer(t)) |
511 return toType(tt.elem) | 503 return toType(tt.elem) |
512 case Ptr: | 504 case Ptr: |
513 tt := (*ptrType)(unsafe.Pointer(t)) | 505 tt := (*ptrType)(unsafe.Pointer(t)) |
514 return toType(tt.elem) | 506 return toType(tt.elem) |
515 case Slice: | 507 case Slice: |
516 tt := (*sliceType)(unsafe.Pointer(t)) | 508 tt := (*sliceType)(unsafe.Pointer(t)) |
517 return toType(tt.elem) | 509 return toType(tt.elem) |
518 } | 510 } |
519 panic("reflect; Elem of invalid type") | 511 panic("reflect; Elem of invalid type") |
520 } | 512 } |
521 | 513 |
522 func (t *commonType) Field(i int) StructField { | 514 func (t *commonType) Field(i int) StructField { |
523 if t.Kind() != Struct { | 515 if t.Kind() != Struct { |
524 panic("reflect: Field of non-struct type") | 516 panic("reflect: Field of non-struct type") |
niemeyer
2011/04/04 13:52:35
It would be helpful to have a TypeError analogous
rsc
2011/04/05 16:29:45
Sure, I will add that in a separate CL.
| |
525 } | 517 } |
526 tt := (*structType)(unsafe.Pointer(t)) | 518 tt := (*structType)(unsafe.Pointer(t)) |
527 return tt.Field(i) | 519 return tt.Field(i) |
528 } | 520 } |
529 | 521 |
530 func (t *commonType) FieldByIndex(index []int) StructField { | 522 func (t *commonType) FieldByIndex(index []int) StructField { |
531 if t.Kind() != Struct { | 523 if t.Kind() != Struct { |
532 panic("reflect: FieldByIndex of non-struct type") | 524 panic("reflect: FieldByIndex of non-struct type") |
533 } | 525 } |
534 tt := (*structType)(unsafe.Pointer(t)) | 526 tt := (*structType)(unsafe.Pointer(t)) |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
676 | 668 |
677 // TODO(gri): Should there be an error/bool indicator if the index | 669 // TODO(gri): Should there be an error/bool indicator if the index |
678 // is wrong for FieldByIndex? | 670 // is wrong for FieldByIndex? |
679 | 671 |
680 // FieldByIndex returns the nested field corresponding to index. | 672 // FieldByIndex returns the nested field corresponding to index. |
681 func (t *structType) FieldByIndex(index []int) (f StructField) { | 673 func (t *structType) FieldByIndex(index []int) (f StructField) { |
682 f.Type = Type(t.toType()) | 674 f.Type = Type(t.toType()) |
683 for i, x := range index { | 675 for i, x := range index { |
684 if i > 0 { | 676 if i > 0 { |
685 ft := f.Type | 677 ft := f.Type |
686 » » » if ft.Kind() == Ptr { | 678 » » » if ft.Kind() == Ptr && ft.Elem().Kind() == Struct { |
687 ft = ft.Elem() | 679 ft = ft.Elem() |
688 } | |
689 if ft.Kind() != Struct { | |
690 return StructField{} | |
niemeyer
2011/04/04 13:52:35
Should we take the chance to make this panic rathe
rsc
2011/04/05 16:29:45
Done.
| |
691 } | 680 } |
692 f.Type = ft | 681 f.Type = ft |
693 } | 682 } |
694 f = f.Type.Field(x) | 683 f = f.Type.Field(x) |
695 } | 684 } |
696 return | 685 return |
697 } | 686 } |
698 | 687 |
699 const inf = 1 << 30 // infinity - no struct has that many nesting levels | 688 const inf = 1 << 30 // infinity - no struct has that many nesting levels |
700 | 689 |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
866 p.hash = ct.hash*16777619 ^ '*' | 855 p.hash = ct.hash*16777619 ^ '*' |
867 | 856 |
868 p.uncommonType = nil | 857 p.uncommonType = nil |
869 p.ptrToThis = nil | 858 p.ptrToThis = nil |
870 p.elem = (*runtime.Type)(unsafe.Pointer(uintptr(unsafe.Pointer(ct)) - ui ntptr(unsafe.Offsetof(rt.ptrType)))) | 859 p.elem = (*runtime.Type)(unsafe.Pointer(uintptr(unsafe.Pointer(ct)) - ui ntptr(unsafe.Offsetof(rt.ptrType)))) |
871 | 860 |
872 ptrMap.m[ct] = p | 861 ptrMap.m[ct] = p |
873 ptrMap.Unlock() | 862 ptrMap.Unlock() |
874 return p.commonType.toType() | 863 return p.commonType.toType() |
875 } | 864 } |
LEFT | RIGHT |