-
Notifications
You must be signed in to change notification settings - Fork 13
/
reflect_01.go
2592 lines (2367 loc) · 103 KB
/
reflect_01.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
package main
import (
"bytes"
base642 "encoding/base64"
"fmt"
"io"
"time"
"os"
"reflect"
"strconv"
)
func main() {
fmt.Println("-------------reflect.Type对象-----------------")
//type Type 对象说明:
//type Type interface {
// // Kind返回该接口的具体分类
// Kind() Kind
// // Name返回该类型在自身包内的类型名,如果是未命名类型会返回""
// Name() string
// // PkgPath返回类型的包路径,即明确指定包的import路径,如"encoding/base64"
// // 如果类型为内建类型(string, error)或未命名类型(*T, struct{}, []int),会返回""
// PkgPath() string
// // 返回类型的字符串表示。该字符串可能会使用短包名(如用base64代替"encoding/base64")
// // 也不保证每个类型的字符串表示不同。如果要比较两个类型是否相等,请直接用Type类型比较。
// String() string
// // 返回要保存一个该类型的值需要多少字节;类似unsafe.Sizeof
// Size() uintptr
// // 返回当从内存中申请一个该类型值时,会对齐的字节数
// Align() int
// // 返回当该类型作为结构体的字段时,会对齐的字节数
// FieldAlign() int
// // 如果该类型实现了u代表的接口,会返回真
// Implements(u Type) bool
// // 如果该类型的值可以直接赋值给u代表的类型,返回真
// AssignableTo(u Type) bool
// // 如该类型的值可以转换为u代表的类型,返回真
// ConvertibleTo(u Type) bool
// // 返回该类型的字位数。如果该类型的Kind不是Int、Uint、Float或Complex,会panic
// Bits() int
// // 返回array类型的长度,如非数组类型将panic
// Len() int
// // 返回该类型的元素类型,如果该类型的Kind不是Array、Chan、Map、Ptr或Slice,会panic
// Elem() Type
// // 返回map类型的键的类型。如非映射类型将panic
// Key() Type
// // 返回一个channel类型的方向,如非通道类型将会panic
// ChanDir() ChanDir
// // 返回struct类型的字段数(匿名字段算作一个字段),如非结构体类型将panic
// NumField() int
// // 返回struct类型的第i个字段的类型,如非结构体或者i不在[0, NumField())内将会panic
// Field(i int) StructField
// // 返回索引序列指定的嵌套字段的类型,
// // 等价于用索引中每个值链式调用本方法,如非结构体将会panic
// FieldByIndex(index []int) StructField
// // 返回该类型名为name的字段(会查找匿名字段及其子字段),
// // 布尔值说明是否找到,如非结构体将panic
// FieldByName(name string) (StructField, bool)
// // 返回该类型第一个字段名满足函数match的字段,布尔值说明是否找到,如非结构体将会panic
// FieldByNameFunc(match func(string) bool) (StructField, bool)
// // 如果函数类型的最后一个输入参数是"..."形式的参数,IsVariadic返回真
// // 如果这样,t.In(t.NumIn() - 1)返回参数的隐式的实际类型(声明类型的切片)
// // 如非函数类型将panic
// IsVariadic() bool
// // 返回func类型的参数个数,如果不是函数,将会panic
// NumIn() int
// // 返回func类型的第i个参数的类型,如非函数或者i不在[0, NumIn())内将会panic
// In(i int) Type
// // 返回func类型的返回值个数,如果不是函数,将会panic
// NumOut() int
// // 返回func类型的第i个返回值的类型,如非函数或者i不在[0, NumOut())内将会panic
// Out(i int) Type
// // 返回该类型的方法集中方法的数目
// // 匿名字段的方法会被计算;主体类型的方法会屏蔽匿名字段的同名方法;
// // 匿名字段导致的歧义方法会滤除
// NumMethod() int
// // 返回该类型方法集中的第i个方法,i不在[0, NumMethod())范围内时,将导致panic
// // 对非接口类型T或*T,返回值的Type字段和Func字段描述方法的未绑定函数状态
// // 对接口类型,返回值的Type字段描述方法的签名,Func字段为nil
// Method(int) Method
// // 根据方法名返回该类型方法集中的方法,使用一个布尔值说明是否发现该方法
// // 对非接口类型T或*T,返回值的Type字段和Func字段描述方法的未绑定函数状态
// // 对接口类型,返回值的Type字段描述方法的签名,Func字段为nil
// MethodByName(string) (Method, bool)
// // 内含隐藏或非导出方法
//}Type类型用来表示一个go类型。
//
//不是所有go类型的Type值都能使用所有方法。请参见每个方法的文档获取使用限制。在调用有分类限定的方法时,
// 应先使用Kind方法获知类型的分类。调用该分类不支持的方法会导致运行时的panic。
str := "hello world!"
var str_I interface{} = "interface string"
//TypeOf返回接口中保存的值的类型,TypeOf(nil)会返回nil。
T := reflect.TypeOf(str)
Ti := reflect.TypeOf(str_I)
fmt.Println("str对象的底层类型为:", T)
fmt.Println("str对象的底层类型为:", Ti)
// Name返回该类型在自身包内的类型名,如果是未命名类型会返回""
fmt.Println(T.Name())
fmt.Println(Ti.Name())
//输出:
//str对象的底层类型为: string
//str对象的底层类型为: string
//string
//string
// String()返回类型的字符串表示。该字符串可能会使用短包名(如用base64代替"encoding/base64")
// 也不保证每个类型的字符串表示不同。如果要比较两个类型是否相等,请直接用Type类型比较。
fmt.Println(T.String())
var buf = new(bytes.Buffer)
T1 := reflect.TypeOf(buf)
fmt.Println(T1.String())
var base64 = new(base642.Encoding)
T2 := reflect.TypeOf(base64)
fmt.Println(T2.String())
//输出:
//string
//*bytes.Buffer
//*base64.Encoding
//// Elem returns a type's element type.(elem返回一个“包含类型”(可以容纳且仅容纳一种其他类型的子元素的类型)包含的的子元素类型)
//// It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.(如果底层类型不是Array, Chan, Map, Ptr, or Slice的话就会抛出异常)
//fmt.Println(T.Elem())
////报错,字符串不是“包含类型”
////panic: reflect: Elem of invalid type
////
////goroutine 1 [running]:
////reflect.(*rtype).Elem(0x4a9f20, 0xc000006018, 0xc00007bec0)
//// C:/Go/src/reflect/type.go:920 +0x14a
////main.main()
//// C:/Users/Administrator/Desktop/go_pro/src/io_pro/main3/compress_zlib.go:130 +0x58d
//var struct1= struct {
// string
// int
// bool
//}{"anko",15,true}
//struc_type:=reflect.TypeOf(struct1)
//fmt.Println(struc_type.Elem())
////报错:
////panic: reflect: Elem of invalid type
////
////goroutine 1 [running]:
////reflect.(*rtype).Elem(0x4bbca0, 0xc00007bef0, 0x4bbca0)
//// C:/Go/src/reflect/type.go:920 +0x14a
////main.main()
//// C:/Users/Administrator/Desktop/go_pro/src/io_pro/main3/compress_zlib.go:146 +0x601
m := map[string]int{"anko": 14, "jerry": 34, "gogo": 20}
T_map := reflect.TypeOf(m)
fmt.Println(T_map.Elem())
//输出:
//int
c := make(chan string, 3)
c <- "这是chan中的第1个元素"
c <- "这是chan中的第2个元素"
c <- "这是chan中的第3个元素"
T_chan := reflect.TypeOf(c)
fmt.Println(T_chan.Elem())
//输出:
//string
array := [3]bool{true, false, true}
T_array := reflect.TypeOf(array)
fmt.Println(T_array.Elem())
//输出:
//bool
array1 := [3][]bool{[]bool{true, false}, []bool{false, true, true}}
T_array1 := reflect.TypeOf(array1)
fmt.Println(T_array1.Elem())
//输出:
//[]bool
//由上可知,返回的类型只会返回第一层级的类型
ls := []byte{97, 98, 99, 100}
T_ls := reflect.TypeOf(ls)
fmt.Println(T_ls.Elem())
//输出:
//uint8
ls1 := []rune{97, 98, 99, 100}
T_ls1 := reflect.TypeOf(ls1)
fmt.Println(T_ls1.Elem())
//输出:
//int32
ls2 := []int16{97, 98, 99, 100}
T_ls2 := reflect.TypeOf(ls2)
fmt.Println(T_ls2.Elem())
//输出:
//int16
ls3 := []string{"ab", "cd", "ef"}
T_ls3 := reflect.TypeOf(ls3)
fmt.Println(T_ls3.Elem())
//输出:
//string
str5 := "ab"
str6 := "cd"
str7 := "ef"
ls4 := []*string{&str5, &str6, &str7}
T_ls4 := reflect.TypeOf(ls4)
fmt.Println(T_ls4.Elem())
//输出:
//*string
ls5 := &([]string{"ab", "cd", "ef"})
T_ls5 := reflect.TypeOf(ls5)
fmt.Println(T_ls5)
fmt.Println(T_ls5.Elem())
//输出:
//*[]string
//[]string
//// Bits returns the size of the type in bits.(Bits返回数字类型type的存储位数大小)
//// It panics if the type's Kind is not one of the
//// sized or unsized Int, Uint, Float, or Complex kinds.(如果类型的kind类型不是unsized Int, Uint, Float, or Complex 的话会跑出异常)
//fmt.Println(T.Bits())
////报错:
////panic: reflect: Bits of non-arithmetic Type string
////
////goroutine 1 [running]:
////reflect.(*rtype).Bits(0x4ab140, 0xc000006018)
//// C:/Go/src/reflect/type.go:776 +0xd1
////main.main()
//// C:/Users/Administrator/Desktop/go_pro/src/io_pro/main3/compress_zlib.go:232 +0x118f
i := int(15)
T_int := reflect.TypeOf(i)
fmt.Println(T_int.Bits())
//输出:
//64
i32 := int32(15)
T_int32 := reflect.TypeOf(i32)
fmt.Println(T_int32.Bits())
//输出:
//32
i8 := int8(15)
T_int8 := reflect.TypeOf(i8)
fmt.Println(T_int8.Bits())
//输出:
//8
f32 := float32(3.14)
T_float32 := reflect.TypeOf(f32)
fmt.Println(T_float32.Bits())
//输出:
//32
f64 := float64(3.14)
T_float64 := reflect.TypeOf(f64)
fmt.Println(T_float64.Bits())
//输出:
//64
fu8 := uint8(3)
T_uint8 := reflect.TypeOf(fu8)
fmt.Println(T_uint8.Bits())
//输出:
//8
Comp64 := complex64(3 + 2i)
T_complex64 := reflect.TypeOf(Comp64)
fmt.Println(Comp64)
fmt.Println(T_complex64.Bits())
//输出:
//(3+2i)
//64
Comp128 := complex128(3 + 2i)
T_complex128 := reflect.TypeOf(Comp128)
fmt.Println(Comp128)
fmt.Println(T_complex128.Bits())
//输出:
//(3+2i)
//128
//Bits()是返回一个数字类型的位长,但是下面的是返回任意类型的存储所需要的字节个数!一个字节等于8位(bit)
// 返回要保存一个该类型的值需要多少字节;类似unsafe.Sizeof
fmt.Println(T.Size())
//输出:
//16
str111 := "abc"
fmt.Println(reflect.TypeOf(str111).Size())
//输出:
//16
str111 = "123456789abcdef012345678903444444444444444444444444"
fmt.Println(reflect.TypeOf(str111).Size())
//输出:
//16,注意,他不是返回值的长度,而是返回值的类型名的长度,也就是len(string),所以不关值的长度大小!
int111 := 123456
fmt.Println(reflect.TypeOf(int111).Size())
//输出:
//8
int111 = 1234567890
T_int111 := reflect.TypeOf(int111)
fmt.Println(T_int111)
fmt.Println(T_int111.Size())
//输出:
//int
//8,这表示保存int这个类型名所需要的长度!
int222 := int64(123456)
fmt.Println(reflect.TypeOf(int222).Size())
//输出:
//8
b1 := true
fmt.Println(reflect.TypeOf(b1).Size())
//输出:
//1
//// NumIn returns a function type's input parameter count.(NumIn返回一个函数的参数个数)
//// It panics if the type's Kind is not Func.(如果调用者不是一个函数类型的话会抛出异常)
//fmt.Println(T.NumIn())
////报错:
////panic: reflect: NumIn of non-func type
////
////goroutine 1 [running]:
////reflect.(*rtype).NumIn(0x4ac140, 0xc000006018)
//// C:/Go/src/reflect/type.go:989 +0x65
////main.main()
//// C:/Users/Administrator/Desktop/go_pro/src/io_pro/main3/compress_zlib.go:341 +0x1ed7
fun := func(str1, str2 string, i int, b bool) string {
return "abc"
}
T_fun := reflect.TypeOf(fun)
fmt.Println(T_fun.NumIn())
//上面的 方法是获取函数的参数个数,但是下面的方法则是获取第几个参数的类型!
// In returns the type of a function type's i'th input parameter.(in返回第几个参数的类型)
// It panics if the type's Kind is not Func.(如果底层不是函数类型的话会抛出异常的)
// It panics if i is not in the range [0, NumIn()).(参数i必须在[0, NumIn())之间)
fmt.Println(T_fun.In(0))
fmt.Println(T_fun.In(1))
fmt.Println(T_fun.In(2))
fmt.Println(T_fun.In(3))
//这里千万不能复用fun变量了,因为2个函数的参数不同,也就是是不同的类型了,函数的参数不同的表示的就是不同的函数类型
fun1 := func(str1 string, i int, b bool) string {
return "abc"
}
T_fun1 := reflect.TypeOf(fun1)
fmt.Println(T_fun1.NumIn())
fmt.Println(T_fun1.In(0))
fmt.Println(T_fun1.In(1))
fmt.Println(T_fun1.In(2))
//fmt.Println(T_fun1.In(3))//这个超过了函数的个数数目
//输出:
// 4
// string
// string
// int
// bool
// 3
// string
// int
// bool
// panic: runtime error: index out of range [3] with length 3
//
// goroutine 1 [running]:
// reflect.(*rtype).In(0x4b5620, 0x3, 0xc00007bbc0, 0x1)
// C:/Go/src/reflect/type.go:960 +0xaf
// main.main()
// C:/Users/Administrator/Desktop/go_pro/src/io_pro/main3/compress_zlib.go:377 +0x2452
// NumMethod returns the number of exported methods in the type's method set.
// (NumMethod返回在类型(这个类型一般是接口)的方法集合中可导出(第一个字母大写)的方法的数目)
fmt.Println(T.NumMethod())
//输出:
//0
ls_b := []byte{97, 98, 99, 100, 101}
T_lsByte := reflect.TypeOf(ls_b)
fmt.Println(T_lsByte.NumMethod())
//输出:
//0
var p = person{"NAKO", 20, true}
p.Setname111("anko")
p.Setage111()
fmt.Println(p)
T_person := reflect.TypeOf(p)
fmt.Println(T_person.NumMethod())
var behav behavior
behav = &p
T_behavior := reflect.TypeOf(behav)
fmt.Println(T_behavior)
fmt.Println(T_behavior.NumMethod())
//输出:
//{anko 18 true}
//0
//*main.person
//2
// Method returns the i'th method in the type's method set.
// It panics if i is not in the range [0, NumMethod()).
//
// For a non-interface type T or *T, the returned Method's Type and Func
// fields describe a function whose first argument is the receiver.
//
// For an interface type, the returned Method's Type field gives the
// method signature, without a receiver, and the Func field is nil.
//
// Only exported methods are accessible and they are sorted in
// lexicographic order.
fmt.Println(T_behavior.Method(0))
fmt.Println(T_behavior.Method(1))
//fmt.Println(T_behavior.Method(2))//超出了接口类型的方法个数
//输出:
//{Setage111 func(*main.person) <func(*main.person) Value> 0}
//{Setname111 func(*main.person, string) error <func(*main.person, string) error Value> 1}
//panic: reflect: Method index out of range
//
//goroutine 1 [running]:
//reflect.(*rtype).Method(0x4f0680, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
// C:/Go/src/reflect/type.go:814 +0x76c
//main.main()
// C:/Users/Administrator/Desktop/go_pro/src/io_pro/main3/compress_zlib.go:438 +0x2ad4
//从上面可以知道他的返回值是一个很复杂的结构,其实是type Method struct类型,下面是这个类型的说明:
fmt.Println("---------reflect.Method对象----------")
//// Method represents a single method.
////Method代表一个方法。
//type Method struct {
// // Name is the method name.
// // PkgPath is the package path that qualifies a lower case (unexported)
// // method name. It is empty for upper case (exported) method names.
// // The combination of PkgPath and Name uniquely identifies a method
// // in a method set.
// // See https://golang.org/ref/spec#Uniqueness_of_identifiers
// // Name是方法名称。
// // PkgPath是限定小写(未导出)方法名称的程序包路径。 大写(导出)的方法名称为空。
// // PkgPath和Name的组合唯一标识 方法集 中的方法。
// //参见https://golang.org/ref/spec#Uniqueness_of_identifiers
// Name string
// PkgPath string
//
// Type Type // method type//方法的类型
// Func Value // func with receiver as first argument //以接收者为第一个参数的func
// Index int // index for Type.Method // Type.Method的索引
//}
fmt.Println("---------通过类实例调用方法----------")
var Cal =Calculate{}
ret := reflect.ValueOf(&Cal).MethodByName("Add").Call([]reflect.Value{reflect.ValueOf(3),reflect.ValueOf(4)})
fmt.Println(ret)
for key, value := range ret {
fmt.Println(key,value)
}
fmt.Println("---------通过类调用方法----------")
method, ok := reflect.TypeOf(&Cal).MethodByName("Add")
if ok{
fmt.Println("method.Name",method.Name)
fmt.Println("method.Type",method.Type)
fmt.Println("method.PkgPath",method.PkgPath)
fmt.Println("method.Index",method.Index)
fmt.Println("method.Func",method.Func)
ret = method.Func.Call([]reflect.Value{reflect.ValueOf(&Cal),reflect.ValueOf(3),reflect.ValueOf(4)})
fmt.Println(ret)
for key, value := range ret {
fmt.Println(key,value)
}
}
//输出:
// [<int Value>]
// 0 7
// -------------------
// method.Name Add
// method.Type func(*main.Calculate, int, int) int
// method.PkgPath
// method.Index 0
// method.Func 0x4c8480
// [<int Value>]
// 0 7
// MethodByName returns the method with that name in the type's
// method set and a boolean indicating if the method was found.
//
// For a non-interface type T or *T, the returned Method's Type and Func
// fields describe a function whose first argument is the receiver.
//
// For an interface type, the returned Method's Type field gives the
// method signature, without a receiver, and the Func field is nil.
fmt.Println(T_behavior.MethodByName("sdsdsds"))
fmt.Println(T_behavior.MethodByName("Setage111"))
fmt.Println(T_behavior.MethodByName("Setname111"))
//输出:
//{ <nil> <invalid Value> 0} false
//{Setage111 func(*main.person) <func(*main.person) Value> 0} true
//{Setname111 func(*main.person, string) error <func(*main.person, string) error Value> 1} true
// Len returns an array type's length.(Len返回一个基类为array类型(不是切片)实例的值的长度)
// It panics if the type's Kind is not Array.(如果不是array类型的话会抛出异常)
arr := [...]string{"hello", "world", "hahah"}
//slice :=[]string{"hello","world","hahah"}
fmt.Println(reflect.TypeOf(arr).Len())
//fmt.Println(reflect.TypeOf(slice).Len())//会报错
//输出:
//3
//panic: reflect: Len of non-array type
//
//goroutine 1 [running]:
//reflect.(*rtype).Len(0x4e30a0, 0x3)
// C:/Go/src/reflect/type.go:973 +0x65
//main.main()
// C:/Users/Administrator/Desktop/go_pro/src/io_pro/main3/compress_zlib.go:496 +0x30b1
// Align returns the alignment in bytes of a value of
// this type when allocated in memory.
//说白了就是返回分配内存时相应类型所分配的类型内存字节数
fmt.Println()
fmt.Println(T.Align())
fmt.Println(reflect.TypeOf(arr).Align())
fmt.Println(reflect.TypeOf(int16(34)).Align())
fmt.Println(reflect.TypeOf(int16(340)).Align())
fmt.Println(reflect.TypeOf(int16(3400)).Align())
fmt.Println(reflect.TypeOf(int8(34)).Align())
fmt.Println(reflect.TypeOf(int64(34)).Align())
fmt.Println(reflect.TypeOf(int64(34000)).Align())
fmt.Println(reflect.TypeOf(interface{}(34)).Align())
fmt.Println(reflect.TypeOf(string("abc")).Align())
fmt.Println(reflect.TypeOf(string("abcsdsdsdsdddddddddddddddddddddddddddddddd")).Align())
fmt.Println(reflect.TypeOf(string("")).Align())
fmt.Println(reflect.TypeOf(struct{}{}).Align())
fmt.Println(reflect.TypeOf(struct {
string
int
}{"anko", 15}).Align())
//注意在创建匿名结构体的 时候两两字段的类型不能相同,也就是结构体中的某一个类型只允许出现一次,同时字段不允许是切片或者数组类型
fmt.Println(reflect.TypeOf(struct {
string
bool
int
byte
}{"anko", true, 90, 'a'}).Align())
fmt.Println(reflect.TypeOf(struct {
string
bool
int
byte
}{}).Align())
//输出:
// 8
// 8
// 2
// 2
// 2
// 1
// 8
// 8
// 8
// 8
// 8
// 8
// 1
// 8
// 8
// 8
// PkgPath returns a defined type's package path, that is, the import path
// that uniquely identifies the package, such as "encoding/base64".
// If the type was predeclared (string, error) or not defined (*T, struct{},
// []int, or A where A is an alias for a non-defined type), the package path
// will be the empty string.
//翻译:PkgPath返回类型的包路径,即明确指定包的import路径,如"encoding/base64"
// 如果类型为内建类型(string, error)或未预先定义类型(*T, struct{}, []int),会返回空字符串
//Pkg:packeage的简写
fmt.Println(T.PkgPath())
fmt.Println(reflect.TypeOf("bs64").PkgPath())
fmt.Println(reflect.TypeOf(int(14)).PkgPath())
var ii = int64(43)
fmt.Println(reflect.TypeOf(ii).PkgPath())
//输出:以上都是内建的类型,返回值都是空字符串
var ls_i []int
ls_i = []int{1, 2, 34}
fmt.Println(reflect.TypeOf(ls_i).PkgPath())
fmt.Println(reflect.TypeOf(struct{}{}).PkgPath())
fmt.Println(reflect.TypeOf(&struct{}{}).PkgPath())
//输出:以上都是未预先定义类型,返回值都是空字符串
var bs64 base642.Encoding
fmt.Println(reflect.TypeOf(bs64).PkgPath())
//输出:
//encoding/base64
var buf1 bytes.Buffer
fmt.Println(reflect.TypeOf(buf1).PkgPath())
//输出:
//bytes
var p1 = person{"p1", 23, false}
T_p1 := reflect.TypeOf(p1)
// NumField returns a struct type's field count.(NumField返回一个结构体的字段总个数)
// It panics if the type's Kind is not Struct.(如果Field的底层类型不是Struct的话会panic)
fmt.Println(T_p1.NumField())
// Field returns a struct type's i'th field.(Field返回一个结构体的第i个字段的类型)
// It panics if the type's Kind is not Struct.(如果Field的底层类型不是Struct的话会panic)
// It panics if i is not in the range [0, NumField()).(如果i不在【0, NumField()】之间的话也会抛出异常,即索引不能超过结构体字段的个数)
//这个方法返回一个对象,的说明如下:
//// A StructField describes a single field in a struct.(A StructField描述在结构体中的单一字段)
//type StructField struct {
// // Name is the field name.(Name是字段的名字)
// Name string
// // PkgPath is the package path that qualifies a lower case (unexported)
// // field name. It is empty for upper case (exported) field names.(PkgPath是非导出字段的包路径,对导出字段该字段为""。)
// // See https://golang.org/ref/spec#Uniqueness_of_identifiers
// PkgPath string
//
// Type Type // field type(字段的类型)
// Tag StructTag // field tag string(字段的标签tag)
// Offset uintptr // offset within struct, in bytes(字段在结构体的字节水平的下标索引位置,struct的第几个字节是该字段的起始位置)
// Index []int // index sequence for Type.FieldByIndex(字段在结构体中的索引,表示按照声明时候的是该结构体中的第几个字段,跟上面的Offset完全不是一个东西,主要用于Type.FieldByIndex方法)
// Anonymous bool // is an embedded field(是否是匿名字段?)
//}
fmt.Printf("%+v\n", T_p1.Field(0))
fmt.Printf("%+v\n", T_p1.Field(1))
fmt.Printf("%+v\n", T_p1.Field(2))
//fmt.Printf("%+v\n",T_p1.Field(3))//报错,超出了结构体字段的个数
//输出:
//3
//{Name:Name PkgPath: Type:string Tag: Offset:0 Index:[0] Anonymous:false}
//{Name:Age PkgPath: Type:int Tag: Offset:16 Index:[1] Anonymous:false}
//{Name:isstudent PkgPath:main Type:bool Tag: Offset:24 Index:[2] Anonymous:false}
ExampleStructTag_Lookup() //这个函数main外的下面被定义
//输出:
// field_0
// (blank)
// (not specified)
// FieldAlign returns the alignment in bytes of a value of
// this type when used as a field in a struct.
// 返回当该类型作为结构体的字段时,会对齐(占领)的字节数
fmt.Println(T_p1.FieldAlign())
fmt.Println(reflect.TypeOf(struct{}{}).FieldAlign())
fmt.Println(reflect.TypeOf([]byte{'a', 'b'}).FieldAlign())
fmt.Println(reflect.TypeOf([]byte{'a', 'b', 'c'}).FieldAlign())
fmt.Println(reflect.TypeOf([]int{'a', 'b', 'c'}).FieldAlign())
fmt.Println(reflect.TypeOf([]int64{'a', 'b', 'c'}).FieldAlign())
fmt.Println(reflect.TypeOf([]string{"wo", "de"}).FieldAlign())
fmt.Println(reflect.TypeOf([]string{"我的世界", "很大"}).FieldAlign())
fmt.Println(reflect.TypeOf("我的世界很大").FieldAlign())
//输出:
// 8
// 1
// 8
// 8
// 8
// 8
// 8
// 8
// 8
// FieldByIndex returns the nested field corresponding
// to the index sequence. It is equivalent to calling Field
// successively for each index i.
// It panics if the type's Kind is not Struct.
// FieldByIndex返回字段序列中的第i个嵌套的字段对应的StructField对象和是否找到该字段的bool值,如非结构体将会panic
fmt.Printf("%+v\n", T_p1.FieldByIndex([]int{0}))
fmt.Printf("%+v\n", T_p1.FieldByIndex([]int{1}))
fmt.Printf("%+v\n", T_p1.FieldByIndex([]int{2}))
//fmt.Printf("%+v",T_p1.FieldByIndex([]int{0,1}))//报错,继续看下面会解释原因
//输出:
//Name:Name PkgPath: Type:string Tag: Offset:0 Index:[0] Anonymous:false}
//{Name:Age PkgPath: Type:int Tag: Offset:16 Index:[1] Anonymous:false}
//{Name:isstudent PkgPath:main Type:bool Tag: Offset:24 Index:[2] Anonymous:false}
var p11 = person11{p1}
T_p11 := reflect.TypeOf(p11)
fmt.Printf("%+v\n", T_p11.FieldByIndex([]int{0})) //第一层级的第0索引字段
fmt.Printf("%+v\n", T_p11.FieldByIndex([]int{0, 0})) //第一层级的第0索引字段包含的第二层级的第0索引的字段
fmt.Printf("%+v\n", T_p11.FieldByIndex([]int{0, 1})) //第一层级的第0索引字段包含的第二层级的第1索引的字段
fmt.Printf("%+v\n", T_p11.FieldByIndex([]int{0, 2})) //第一层级的第0索引字段包含的第二层级的第2索引的字段
//fmt.Printf("%+v\n",T_p11.FieldByIndex([]int{0,2,0}))//报错,最多2层级而已
//输出:
//{Name:person PkgPath:main Type:main.person Tag: Offset:0 Index:[0] Anonymous:true}
//{Name:Name PkgPath: Type:string Tag: Offset:0 Index:[0] Anonymous:false}
//{Name:Age PkgPath: Type:int Tag: Offset:16 Index:[1] Anonymous:false}
//{Name:isstudent PkgPath:main Type:bool Tag: Offset:24 Index:[2] Anonymous:false}
// FieldByName returns the struct field with the given name
// and a boolean indicating if the field was found.
// 返回该类型名为name的字段(会查找匿名字段及其子字段),
// 布尔值说明是否找到,如非结构体将panic
fmt.Println()
fmt.Println(T_p1.FieldByName("name"))
fmt.Println(T_p1.FieldByName("Name"))
fmt.Println(T_p1.FieldByName("Age"))
fmt.Println(T_p1.FieldByName("isstudent"))
fmt.Println()
fmt.Println(T_p11.FieldByName("name"))
fmt.Println(T_p11.FieldByName("person"))
fmt.Println(T_p11.FieldByName("Name"))
fmt.Println(T_p11.FieldByName("Age"))
fmt.Println(T_p11.FieldByName("isstudent"))
//输出:
//{ <nil> 0 [] false} false
//{Name string 0 [0] false} true
//{Age int 16 [1] false} true
//{isstudent main bool 24 [2] false} true
//
//{ <nil> 0 [] false} false
//{person main main.person 0 [0] true} true
//{Name string 0 [0 0] false} true
//{Age int 16 [0 1] false} true
//{isstudent main bool 24 [0 2] false} true
// FieldByNameFunc returns the struct field with a name
// that satisfies the match function and a boolean indicating if
// the field was found.(返回结构体中第一个字段的name满足函数func的字段对应的StructField对象和是否找到该字段的bool值,如非结构体将会panic(会查找匿名字段及其子字段))
//
// FieldByNameFunc considers the fields in the struct itself
// and then the fields in any embedded structs, in breadth first order,
// stopping at the shallowest nesting depth containing one or more
// fields satisfying the match function. If multiple fields at that depth
// satisfy the match function, they cancel each other
// and FieldByNameFunc returns no match.
// This behavior mirrors Go's handling of name lookup in
// structs containing embedded fields.(没翻译)
fmt.Println()
fmt.Println(T_p1.FieldByNameFunc(func(s string) bool {
if s == "Name" { //其实这里可以按照某个正则规则来进行查找的!但是返回的却永远是第一个符合该条件的字段,下同
return true
}
return false
}))
fmt.Println(T_p1.FieldByNameFunc(func(s string) bool {
if s == "Age" {
return true
}
return false
}))
fmt.Println(T_p1.FieldByNameFunc(func(s string) bool {
if s == "isstudent" {
return true
}
return false
}))
fmt.Println()
fmt.Println(T_p11.NumField())
fmt.Println(T_p11.FieldByNameFunc(func(s string) bool {
if s == "person" {
return true
}
return false
}))
fmt.Println(T_p11.FieldByNameFunc(func(s string) bool {
if s == "Name" {
return true
}
return false
}))
fmt.Println(T_p11.FieldByNameFunc(func(s string) bool {
if s == "Age" {
return true
}
return false
}))
fmt.Println(T_p11.FieldByNameFunc(func(s string) bool {
if s == "isstudent" {
return true
}
return false
}))
//以上输出:
//{Name string 0 [0] false} true
//{Age int 16 [1] false} true
//{isstudent main bool 24 [2] false} true
//
//1
//{person main main.person 0 [0] true} true
//{Name string 0 [0 0] false} true
//{Age int 16 [0 1] false} true
//{isstudent main bool 24 [0 2] false} true
//// A Kind represents the specific kind of type that a Type represents.
//// The zero Kind is not a valid kind.
//type Kind uint
//const (
// Invalid Kind = iota
// Bool
// Int
// Int8
// Int16
// Int32
// Int64
// Uint
// Uint8
// Uint16
// Uint32
// Uint64
// Uintptr
// Float32
// Float64
// Complex64
// Complex128
// Array
// Chan
// Func
// Interface
// Map
// Ptr
// Slice
// String
// Struct
// UnsafePointer
//)
fmt.Println()
fmt.Println(T_p1.Kind())
fmt.Println(T_p11.Kind())
fmt.Println(T.Kind())
fmt.Println(reflect.TypeOf([]byte{'a', 'b'}).Kind())
fmt.Println(reflect.TypeOf([2]byte{'a', 'b'}).Kind())
fmt.Println(reflect.TypeOf([2]int{'a', 'b'}).Kind())
fmt.Println(reflect.TypeOf(int('a')).Kind())
fmt.Println(reflect.TypeOf(uint('a')).Kind())
fmt.Println(reflect.TypeOf(float32('a')).Kind())
fmt.Println(reflect.TypeOf(float64('a')).Kind())
fmt.Println(reflect.TypeOf(complex64('a')).Kind())
fmt.Println(reflect.TypeOf(complex128('a')).Kind())
fmt.Println(reflect.TypeOf(true).Kind())
fmt.Println(reflect.TypeOf(map[string]int{"a": 97, "b": 98}).Kind())
fmt.Println(reflect.TypeOf(interface{}(16)).Kind())
fmt.Println(reflect.TypeOf(interface{}("aaa")).Kind())
fmt.Println(reflect.TypeOf((*int)(nil)).Kind())
fmt.Println(reflect.TypeOf((func())(nil)).Kind())
fmt.Println(reflect.TypeOf((chan int)(nil)).Kind())
fmt.Println(reflect.TypeOf((map[string]int)(nil)).Kind())
fmt.Println(reflect.TypeOf(([]byte)(nil)).Kind())
fmt.Println(reflect.TypeOf(struct{}{}).Kind())
fmt.Println(reflect.TypeOf(person{}).Kind())
//fmt.Println(reflect.TypeOf(([2]byte)(nil)).Kind())//报错,nil可以转化为引用类型,但是不能转化为值类型
//fmt.Println(reflect.TypeOf(interface{}(nil)).Kind())//报错,nil可以转化为引用类型,但是不能转化为值类型
//输出:
//struct
//struct
//string
//slice
//array
//array
//int
//uint
//float32
//float64
//complex64
//complex128
//bool
//map
//int
//string
//ptr
//func
//chan
//map
//slice
//struct
// Key returns a map type's key type.
// It panics if the type's Kind is not Map.
// Key返回一个map的键key的类型,非map类型的话会抛出异常
//fmt.Println(T_p1.Key())//报错
fmt.Println()
m1 := map[string]int{"a": 97, "b": 98}
m2 := map[interface{}]int{nil: 97, nil: 98} //nil也可以作为键
m3 := map[person]int{person{"a", 13, true}: 97, person{"b", 13, true}: 98}
var beh1 behavior
var beh2 behavior
m4 := map[behavior]int{beh1: 76, beh2: 87}
T_m1 := reflect.TypeOf(m1)
T_m2 := reflect.TypeOf(m2)
T_m3 := reflect.TypeOf(m3)
T_m4 := reflect.TypeOf(m4)
fmt.Println(T_m1.Key())
fmt.Println(T_m2.Key())
fmt.Println(T_m3.Key())
fmt.Println(T_m4.Key())
//输出:
//string
//interface {}
//main.person
//main.behavior
fmt.Println()
T_f2 := reflect.TypeOf(f2)
T_f3 := reflect.TypeOf(f3)
// NumOut returns a function type's output parameter count.(返回函数的返回值个数,非函数类型会报错)
// It panics if the type's Kind is not Func.
fmt.Println(T_f2.NumOut())
fmt.Println(T_f3.NumOut())
// Out returns the type of a function type's i'th output parameter.(返回函数的第i个返回值的类型,非函数类型会报错,i必须属于[0, NumOut())之中的整数)
// It panics if the type's Kind is not Func.
// It panics if i is not in the range [0, NumOut()).
fmt.Println(T_f2.Out(0))
fmt.Println(T_f2.Out(1))
//输出:
//2
//0
//string
//error
fmt.Println()
f4 := func(int, ...float64) {}
f5 := func(int, float64) {}
T_f4 := reflect.TypeOf(f4)
T_f5 := reflect.TypeOf(f5)
// IsVariadic reports whether a function type's final input parameter
// is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the parameter's
// implicit actual type []T.
//
// For concreteness, if t represents func(x int, y ... float64), then
//
// t.NumIn() == 2
// t.In(0) is the reflect.Type for "int"
// t.In(1) is the reflect.Type for "[]float64"
// t.IsVariadic() == true
//
// IsVariadic panics if the type's Kind is not Func.
//IsVariadic判断函数的参数中是否有...int(或者其他类型,不一定是int)这样的类型,非函数类型的话会报错
fmt.Println(T_f4.IsVariadic())
fmt.Println(T_f4.NumIn())
fmt.Println(T_f4.In(0))
fmt.Println(T_f4.In(1))
fmt.Println(T_f5.IsVariadic())
fmt.Println(T_f5.NumIn())
fmt.Println(T_f5.In(0))
fmt.Println(T_f5.In(1))
//fmt.Println(T.IsVariadic())//报错,类型不对
//输出:
// true
// 2
// int
// []float64,虽然在这里输出的是[]float64,但是我们在定义函数的参数时候不能这样写,这跟...float64这样定义参数的函数的调用方式是不一样的!
// false
// 2
// int
// float64
fmt.Println()
c_all := make(chan int, 2) ///定义存取int类型值的通道(chan和int之间必须空格)
c_in := make(chan<- int, 2) //定义存int类型值的通道(chan和int之间可以空格,非必须,但是建议)
c_out := make(<-chan int, 2) //定义取int类型值的通道(chan和int之间必须空格)
//var c_out <-chan
T_c_all := reflect.TypeOf(c_all)
T_c_in := reflect.TypeOf(c_in)
T_c_out := reflect.TypeOf(c_out)
// ChanDir returns a channel type's direction.(ChanDir返回一个chan的具体类型,是取值通道 还是 存值通道 或者是既可以取值又可以存值的通道)
// It panics if the type's Kind is not Chan.(非通道类型会报错)
fmt.Println(T_c_all.ChanDir())
fmt.Println(T_c_in.ChanDir())
fmt.Println(T_c_out.ChanDir())
//输出:
//chan
//chan<-
//<-chan
fmt.Println()
// Comparable reports whether values of this type are comparable.(判断类型的值是否可以比较)
fmt.Println(T.Comparable())
fmt.Println(reflect.TypeOf(int(24)).Comparable())
fmt.Println(reflect.TypeOf(int64(24)).Comparable())
fmt.Println(reflect.TypeOf(string(24)).Comparable())
fmt.Println(reflect.TypeOf(bool(true)).Comparable())
fmt.Println(reflect.TypeOf(struct{}{}).Comparable())
var k interface{}