LEFT | RIGHT |
1 <!--{ | 1 <!--{ |
2 "Title": "The Laws of Reflection" | 2 "Title": "The Laws of Reflection" |
3 }--> | 3 }--> |
4 <!-- | 4 <!-- |
5 DO NOT EDIT: created by | 5 DO NOT EDIT: created by |
6 tmpltohtml articles/laws_of_reflection.tmpl | 6 tmpltohtml articles/laws_of_reflection.tmpl |
7 --> | 7 --> |
8 | 8 |
9 | 9 |
10 <p> | 10 <p> |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 fmt.Println("kind is uint8: ", v.Kind() == reflect.Uint8) // true. | 349 fmt.Println("kind is uint8: ", v.Kind() == reflect.Uint8) // true. |
350 x = uint8(v.Uint()) // v.Uint returns
a uint64.</pre> | 350 x = uint8(v.Uint()) // v.Uint returns
a uint64.</pre> |
351 | 351 |
352 <p> | 352 <p> |
353 The second property is that the <code>Kind</code> of a reflection | 353 The second property is that the <code>Kind</code> of a reflection |
354 object describes the underlying type, not the static type. If a | 354 object describes the underlying type, not the static type. If a |
355 reflection object contains a value of a user-defined integer type, | 355 reflection object contains a value of a user-defined integer type, |
356 as in | 356 as in |
357 </p> | 357 </p> |
358 | 358 |
359 <pre><!--{{code "progs/interface2.go" `/START f3/` `/START/`}} | 359 <pre><!--{{code "progs/interface2.go" `/START f3/` `/STOP/`}} |
360 --> type MyInt int | 360 --> type MyInt int |
361 var x MyInt = 7 | 361 var x MyInt = 7 |
362 v := reflect.ValueOf(x)</pre> | 362 v := reflect.ValueOf(x)</pre> |
363 | 363 |
364 <p> | 364 <p> |
365 the <code>Kind</code> of <code>v</code> is still | 365 the <code>Kind</code> of <code>v</code> is still |
366 <code>reflect.Int</code>, even though the static type of | 366 <code>reflect.Int</code>, even though the static type of |
367 <code>x</code> is <code>MyInt</code>, not <code>int</code>. In | 367 <code>x</code> is <code>MyInt</code>, not <code>int</code>. In |
368 other words, the <code>Kind</code> cannot discriminate an int from | 368 other words, the <code>Kind</code> cannot discriminate an int from |
369 a <code>MyInt</code> even though the <code>Type</code> can. | 369 a <code>MyInt</code> even though the <code>Type</code> can. |
(...skipping 18 matching lines...) Expand all Loading... |
388 | 388 |
389 <pre> | 389 <pre> |
390 // Interface returns v's value as an interface{}. | 390 // Interface returns v's value as an interface{}. |
391 func (v Value) Interface() interface{} | 391 func (v Value) Interface() interface{} |
392 </pre> | 392 </pre> |
393 | 393 |
394 <p> | 394 <p> |
395 As a consequence we can say | 395 As a consequence we can say |
396 </p> | 396 </p> |
397 | 397 |
398 <pre><!--{{code "progs/interface2.go" `/START f3b/` `/START/`}} | 398 <pre><!--{{code "progs/interface2.go" `/START f3b/` `/STOP/`}} |
399 --> y := v.Interface().(float64) // y will have type float64. | 399 --> y := v.Interface().(float64) // y will have type float64. |
400 fmt.Println(y)</pre> | 400 fmt.Println(y)</pre> |
401 | 401 |
402 <p> | 402 <p> |
403 to print the <code>float64</code> value represented by the | 403 to print the <code>float64</code> value represented by the |
404 reflection object <code>v</code>. | 404 reflection object <code>v</code>. |
405 </p> | 405 </p> |
406 | 406 |
407 <p> | 407 <p> |
408 We can do even better, though. The arguments to | 408 We can do even better, though. The arguments to |
409 <code>fmt.Println</code>, <code>fmt.Printf</code> and so on are all | 409 <code>fmt.Println</code>, <code>fmt.Printf</code> and so on are all |
410 passed as empty interface values, which are then unpacked by the | 410 passed as empty interface values, which are then unpacked by the |
411 <code>fmt</code> package internally just as we have been doing in | 411 <code>fmt</code> package internally just as we have been doing in |
412 the previous examples. Therefore all it takes to print the contents | 412 the previous examples. Therefore all it takes to print the contents |
413 of a <code>reflect.Value</code> correctly is to pass the result of | 413 of a <code>reflect.Value</code> correctly is to pass the result of |
414 the <code>Interface</code> method to the formatted print | 414 the <code>Interface</code> method to the formatted print |
415 routine: | 415 routine: |
416 </p> | 416 </p> |
417 | 417 |
418 <pre><!--{{code "progs/interface2.go" `/START f3c/` `/START/`}} | 418 <pre><!--{{code "progs/interface2.go" `/START f3c/` `/STOP/`}} |
419 --> fmt.Println(v.Interface())</pre> | 419 --> fmt.Println(v.Interface())</pre> |
420 | 420 |
421 <p> | 421 <p> |
422 (Why not <code>fmt.Println(v)</code>? Because <code>v</code> is a | 422 (Why not <code>fmt.Println(v)</code>? Because <code>v</code> is a |
423 <code>reflect.Value</code>; we want the concrete value it holds.) | 423 <code>reflect.Value</code>; we want the concrete value it holds.) |
424 Since our value is a <code>float64</code>, we can even use a | 424 Since our value is a <code>float64</code>, we can even use a |
425 floating-point format if we want: | 425 floating-point format if we want: |
426 </p> | 426 </p> |
427 | 427 |
428 <pre><!--{{code "progs/interface2.go" `/START f3d/` `/STOP/`}} | 428 <pre><!--{{code "progs/interface2.go" `/START f3d/` `/STOP/`}} |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 </p> | 511 </p> |
512 | 512 |
513 <p> | 513 <p> |
514 Settability is a bit like addressability, but stricter. It's the | 514 Settability is a bit like addressability, but stricter. It's the |
515 property that a reflection object can modify the actual storage | 515 property that a reflection object can modify the actual storage |
516 that was used to create the reflection object. Settability is | 516 that was used to create the reflection object. Settability is |
517 determined by whether the reflection object holds the original | 517 determined by whether the reflection object holds the original |
518 item. When we say | 518 item. When we say |
519 </p> | 519 </p> |
520 | 520 |
521 <pre><!--{{code "progs/interface2.go" `/START f6/` `/START/`}} | 521 <pre><!--{{code "progs/interface2.go" `/START f6/` `/STOP/`}} |
522 --> var x float64 = 3.4 | 522 --> var x float64 = 3.4 |
523 v := reflect.ValueOf(x)</pre> | 523 v := reflect.ValueOf(x)</pre> |
524 | 524 |
525 <p> | 525 <p> |
526 we pass a <em>copy</em> of <code>x</code> to | 526 we pass a <em>copy</em> of <code>x</code> to |
527 <code>reflect.ValueOf</code>, so the interface value created as the | 527 <code>reflect.ValueOf</code>, so the interface value created as the |
528 argument to <code>reflect.ValueOf</code> is a <em>copy</em> of | 528 argument to <code>reflect.ValueOf</code> is a <em>copy</em> of |
529 <code>x</code>, not <code>x</code> itself. Thus, if the | 529 <code>x</code>, not <code>x</code> itself. Thus, if the |
530 statement | 530 statement |
531 </p> | 531 </p> |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
570 give the reflection library a pointer to the value we want to | 570 give the reflection library a pointer to the value we want to |
571 modify. | 571 modify. |
572 </p> | 572 </p> |
573 | 573 |
574 <p> | 574 <p> |
575 Let's do that. First we initialize <code>x</code> as usual | 575 Let's do that. First we initialize <code>x</code> as usual |
576 and then create a reflection value that points to it, called | 576 and then create a reflection value that points to it, called |
577 <code>p</code>. | 577 <code>p</code>. |
578 </p> | 578 </p> |
579 | 579 |
580 <pre><!--{{code "progs/interface2.go" `/START f7/` `/START/`}} | 580 <pre><!--{{code "progs/interface2.go" `/START f7/` `/STOP/`}} |
581 --> var x float64 = 3.4 | 581 --> var x float64 = 3.4 |
582 p := reflect.ValueOf(&x) // Note: take the address of x. | 582 p := reflect.ValueOf(&x) // Note: take the address of x. |
583 fmt.Println("type of p:", p.Type()) | 583 fmt.Println("type of p:", p.Type()) |
584 fmt.Println("settability of p:", p.CanSet())</pre> | 584 fmt.Println("settability of p:", p.CanSet())</pre> |
585 | 585 |
586 <p> | 586 <p> |
587 The output so far is | 587 The output so far is |
588 </p> | 588 </p> |
589 | 589 |
590 <pre> | 590 <pre> |
591 type of p: *float64 | 591 type of p: *float64 |
592 settability of p: false | 592 settability of p: false |
593 </pre> | 593 </pre> |
594 | 594 |
595 <p> | 595 <p> |
596 The reflection object <code>p</code> isn't settable, but it's not | 596 The reflection object <code>p</code> isn't settable, but it's not |
597 <code>p</code> we want to set, it's (in effect) <code>*p</code>. To | 597 <code>p</code> we want to set, it's (in effect) <code>*p</code>. To |
598 get to what <code>p</code> points to, we call the <code>Elem</code> | 598 get to what <code>p</code> points to, we call the <code>Elem</code> |
599 method of <code>Value</code>, which indirects through the pointer, | 599 method of <code>Value</code>, which indirects through the pointer, |
600 and save the result in a reflection <code>Value</code> called | 600 and save the result in a reflection <code>Value</code> called |
601 <code>v</code>: | 601 <code>v</code>: |
602 </p> | 602 </p> |
603 | 603 |
604 <pre><!--{{code "progs/interface2.go" `/START f7b/` `/START/`}} | 604 <pre><!--{{code "progs/interface2.go" `/START f7b/` `/STOP/`}} |
605 --> v := p.Elem() | 605 --> v := p.Elem() |
606 fmt.Println("settability of v:", v.CanSet())</pre> | 606 fmt.Println("settability of v:", v.CanSet())</pre> |
607 | 607 |
608 <p> | 608 <p> |
609 Now <code>v</code> is a settable reflection object, as the output | 609 Now <code>v</code> is a settable reflection object, as the output |
610 demonstrates, | 610 demonstrates, |
611 </p> | 611 </p> |
612 | 612 |
613 <pre> | 613 <pre> |
614 settability of v: true | 614 settability of v: true |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
657 <code>t</code>. We create the reflection object with the address of | 657 <code>t</code>. We create the reflection object with the address of |
658 the struct because we'll want to modify it later. Then we set | 658 the struct because we'll want to modify it later. Then we set |
659 <code>typeOfT</code> to its type and iterate over the fields using | 659 <code>typeOfT</code> to its type and iterate over the fields using |
660 straightforward method calls (see· | 660 straightforward method calls (see· |
661 <a href="http://golang.org/pkg/reflect/">package reflect</a> for details). | 661 <a href="http://golang.org/pkg/reflect/">package reflect</a> for details). |
662 Note that we extract the names of the fields from the struct type, | 662 Note that we extract the names of the fields from the struct type, |
663 but the fields themselves are regular <code>reflect.Value</code> | 663 but the fields themselves are regular <code>reflect.Value</code> |
664 objects. | 664 objects. |
665 </p> | 665 </p> |
666 | 666 |
667 <pre><!--{{code "progs/interface2.go" `/START f8/` `/START/`}} | 667 <pre><!--{{code "progs/interface2.go" `/START f8/` `/STOP/`}} |
668 --> type T struct { | 668 --> type T struct { |
669 A int | 669 A int |
670 B string | 670 B string |
671 } | 671 } |
672 t := T{23, "skidoo"} | 672 t := T{23, "skidoo"} |
673 s := reflect.ValueOf(&t).Elem() | 673 s := reflect.ValueOf(&t).Elem() |
674 typeOfT := s.Type() | 674 typeOfT := s.Type() |
675 for i := 0; i < s.NumField(); i++ { | 675 for i := 0; i < s.NumField(); i++ { |
676 f := s.Field(i) | 676 f := s.Field(i) |
677 fmt.Printf("%d: %s %s = %v\n", i, | 677 fmt.Printf("%d: %s %s = %v\n", i, |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
740 necessary. | 740 necessary. |
741 </p> | 741 </p> |
742 | 742 |
743 <p> | 743 <p> |
744 There's plenty more to reflection that we haven't covered — | 744 There's plenty more to reflection that we haven't covered — |
745 sending and receiving on channels, allocating memory, using slices | 745 sending and receiving on channels, allocating memory, using slices |
746 and maps, calling methods and functions — but this post is | 746 and maps, calling methods and functions — but this post is |
747 long enough. We'll cover some of those topics in a later | 747 long enough. We'll cover some of those topics in a later |
748 article. | 748 article. |
749 </p> | 749 </p> |
LEFT | RIGHT |