| // Copyright 2012 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package reflect_test |
| |
| import ( |
| "bytes" |
| "encoding/json" |
| "fmt" |
| "io" |
| "os" |
| "reflect" |
| ) |
| |
| func ExampleKind() { |
| for _, v := range []any{"hi", 42, func() {}} { |
| switch v := reflect.ValueOf(v); v.Kind() { |
| case reflect.String: |
| fmt.Println(v.String()) |
| case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: |
| fmt.Println(v.Int()) |
| default: |
| fmt.Printf("unhandled kind %s", v.Kind()) |
| } |
| } |
| |
| // Output: |
| // hi |
| // 42 |
| // unhandled kind func |
| } |
| |
| func ExampleMakeFunc() { |
| // swap is the implementation passed to MakeFunc. |
| // It must work in terms of reflect.Values so that it is possible |
| // to write code without knowing beforehand what the types |
| // will be. |
| swap := func(in []reflect.Value) []reflect.Value { |
| return []reflect.Value{in[1], in[0]} |
| } |
| |
| // makeSwap expects fptr to be a pointer to a nil function. |
| // It sets that pointer to a new function created with MakeFunc. |
| // When the function is invoked, reflect turns the arguments |
| // into Values, calls swap, and then turns swap's result slice |
| // into the values returned by the new function. |
| makeSwap := func(fptr any) { |
| // fptr is a pointer to a function. |
| // Obtain the function value itself (likely nil) as a reflect.Value |
| // so that we can query its type and then set the value. |
| fn := reflect.ValueOf(fptr).Elem() |
| |
| // Make a function of the right type. |
| v := reflect.MakeFunc(fn.Type(), swap) |
| |
| // Assign it to the value fn represents. |
| fn.Set(v) |
| } |
| |
| // Make and call a swap function for ints. |
| var intSwap func(int, int) (int, int) |
| makeSwap(&intSwap) |
| fmt.Println(intSwap(0, 1)) |
| |
| // Make and call a swap function for float64s. |
| var floatSwap func(float64, float64) (float64, float64) |
| makeSwap(&floatSwap) |
| fmt.Println(floatSwap(2.72, 3.14)) |
| |
| // Output: |
| // 1 0 |
| // 3.14 2.72 |
| } |
| |
| func ExampleStructTag() { |
| type S struct { |
| F string `species:"gopher" color:"blue"` |
| } |
| |
| s := S{} |
| st := reflect.TypeOf(s) |
| field := st.Field(0) |
| fmt.Println(field.Tag.Get("color"), field.Tag.Get("species")) |
| |
| // Output: |
| // blue gopher |
| } |
| |
| func ExampleStructTag_Lookup() { |
| type S struct { |
| F0 string `alias:"field_0"` |
| F1 string `alias:""` |
| F2 string |
| } |
| |
| s := S{} |
| st := reflect.TypeOf(s) |
| for i := 0; i < st.NumField(); i++ { |
| field := st.Field(i) |
| if alias, ok := field.Tag.Lookup("alias"); ok { |
| if alias == "" { |
| fmt.Println("(blank)") |
| } else { |
| fmt.Println(alias) |
| } |
| } else { |
| fmt.Println("(not specified)") |
| } |
| } |
| |
| // Output: |
| // field_0 |
| // (blank) |
| // (not specified) |
| } |
| |
| func ExampleTypeOf() { |
| // As interface types are only used for static typing, a |
| // common idiom to find the reflection Type for an interface |
| // type Foo is to use a *Foo value. |
| writerType := reflect.TypeOf((*io.Writer)(nil)).Elem() |
| |
| fileType := reflect.TypeOf((*os.File)(nil)) |
| fmt.Println(fileType.Implements(writerType)) |
| |
| // Output: |
| // true |
| } |
| |
| func ExampleStructOf() { |
| typ := reflect.StructOf([]reflect.StructField{ |
| { |
| Name: "Height", |
| Type: reflect.TypeOf(float64(0)), |
| Tag: `json:"height"`, |
| }, |
| { |
| Name: "Age", |
| Type: reflect.TypeOf(int(0)), |
| Tag: `json:"age"`, |
| }, |
| }) |
| |
| v := reflect.New(typ).Elem() |
| v.Field(0).SetFloat(0.4) |
| v.Field(1).SetInt(2) |
| s := v.Addr().Interface() |
| |
| w := new(bytes.Buffer) |
| if err := json.NewEncoder(w).Encode(s); err != nil { |
| panic(err) |
| } |
| |
| fmt.Printf("value: %+v\n", s) |
| fmt.Printf("json: %s", w.Bytes()) |
| |
| r := bytes.NewReader([]byte(`{"height":1.5,"age":10}`)) |
| if err := json.NewDecoder(r).Decode(s); err != nil { |
| panic(err) |
| } |
| fmt.Printf("value: %+v\n", s) |
| |
| // Output: |
| // value: &{Height:0.4 Age:2} |
| // json: {"height":0.4,"age":2} |
| // value: &{Height:1.5 Age:10} |
| } |
| |
| func ExampleValue_FieldByIndex() { |
| // This example shows a case in which the name of a promoted field |
| // is hidden by another field: FieldByName will not work, so |
| // FieldByIndex must be used instead. |
| type user struct { |
| firstName string |
| lastName string |
| } |
| |
| type data struct { |
| user |
| firstName string |
| lastName string |
| } |
| |
| u := data{ |
| user: user{"Embedded John", "Embedded Doe"}, |
| firstName: "John", |
| lastName: "Doe", |
| } |
| |
| s := reflect.ValueOf(u).FieldByIndex([]int{0, 1}) |
| fmt.Println("embedded last name:", s) |
| |
| // Output: |
| // embedded last name: Embedded Doe |
| } |
| |
| func ExampleValue_FieldByName() { |
| type user struct { |
| firstName string |
| lastName string |
| } |
| u := user{firstName: "John", lastName: "Doe"} |
| s := reflect.ValueOf(u) |
| |
| fmt.Println("Name:", s.FieldByName("firstName")) |
| // Output: |
| // Name: John |
| } |