1// Copyright 2012 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package reflect_test
6
7import (
8	"bytes"
9	"encoding/json"
10	"fmt"
11	"io"
12	"os"
13	"reflect"
14)
15
16func ExampleKind() {
17	for _, v := range []any{"hi", 42, func() {}} {
18		switch v := reflect.ValueOf(v); v.Kind() {
19		case reflect.String:
20			fmt.Println(v.String())
21		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
22			fmt.Println(v.Int())
23		default:
24			fmt.Printf("unhandled kind %s", v.Kind())
25		}
26	}
27
28	// Output:
29	// hi
30	// 42
31	// unhandled kind func
32}
33
34func ExampleMakeFunc() {
35	// swap is the implementation passed to MakeFunc.
36	// It must work in terms of reflect.Values so that it is possible
37	// to write code without knowing beforehand what the types
38	// will be.
39	swap := func(in []reflect.Value) []reflect.Value {
40		return []reflect.Value{in[1], in[0]}
41	}
42
43	// makeSwap expects fptr to be a pointer to a nil function.
44	// It sets that pointer to a new function created with MakeFunc.
45	// When the function is invoked, reflect turns the arguments
46	// into Values, calls swap, and then turns swap's result slice
47	// into the values returned by the new function.
48	makeSwap := func(fptr any) {
49		// fptr is a pointer to a function.
50		// Obtain the function value itself (likely nil) as a reflect.Value
51		// so that we can query its type and then set the value.
52		fn := reflect.ValueOf(fptr).Elem()
53
54		// Make a function of the right type.
55		v := reflect.MakeFunc(fn.Type(), swap)
56
57		// Assign it to the value fn represents.
58		fn.Set(v)
59	}
60
61	// Make and call a swap function for ints.
62	var intSwap func(int, int) (int, int)
63	makeSwap(&intSwap)
64	fmt.Println(intSwap(0, 1))
65
66	// Make and call a swap function for float64s.
67	var floatSwap func(float64, float64) (float64, float64)
68	makeSwap(&floatSwap)
69	fmt.Println(floatSwap(2.72, 3.14))
70
71	// Output:
72	// 1 0
73	// 3.14 2.72
74}
75
76func ExampleStructTag() {
77	type S struct {
78		F string `species:"gopher" color:"blue"`
79	}
80
81	s := S{}
82	st := reflect.TypeOf(s)
83	field := st.Field(0)
84	fmt.Println(field.Tag.Get("color"), field.Tag.Get("species"))
85
86	// Output:
87	// blue gopher
88}
89
90func ExampleStructTag_Lookup() {
91	type S struct {
92		F0 string `alias:"field_0"`
93		F1 string `alias:""`
94		F2 string
95	}
96
97	s := S{}
98	st := reflect.TypeOf(s)
99	for i := 0; i < st.NumField(); i++ {
100		field := st.Field(i)
101		if alias, ok := field.Tag.Lookup("alias"); ok {
102			if alias == "" {
103				fmt.Println("(blank)")
104			} else {
105				fmt.Println(alias)
106			}
107		} else {
108			fmt.Println("(not specified)")
109		}
110	}
111
112	// Output:
113	// field_0
114	// (blank)
115	// (not specified)
116}
117
118func ExampleTypeOf() {
119	// As interface types are only used for static typing, a
120	// common idiom to find the reflection Type for an interface
121	// type Foo is to use a *Foo value.
122	writerType := reflect.TypeOf((*io.Writer)(nil)).Elem()
123
124	fileType := reflect.TypeOf((*os.File)(nil))
125	fmt.Println(fileType.Implements(writerType))
126
127	// Output:
128	// true
129}
130
131func ExampleStructOf() {
132	typ := reflect.StructOf([]reflect.StructField{
133		{
134			Name: "Height",
135			Type: reflect.TypeOf(float64(0)),
136			Tag:  `json:"height"`,
137		},
138		{
139			Name: "Age",
140			Type: reflect.TypeOf(int(0)),
141			Tag:  `json:"age"`,
142		},
143	})
144
145	v := reflect.New(typ).Elem()
146	v.Field(0).SetFloat(0.4)
147	v.Field(1).SetInt(2)
148	s := v.Addr().Interface()
149
150	w := new(bytes.Buffer)
151	if err := json.NewEncoder(w).Encode(s); err != nil {
152		panic(err)
153	}
154
155	fmt.Printf("value: %+v\n", s)
156	fmt.Printf("json:  %s", w.Bytes())
157
158	r := bytes.NewReader([]byte(`{"height":1.5,"age":10}`))
159	if err := json.NewDecoder(r).Decode(s); err != nil {
160		panic(err)
161	}
162	fmt.Printf("value: %+v\n", s)
163
164	// Output:
165	// value: &{Height:0.4 Age:2}
166	// json:  {"height":0.4,"age":2}
167	// value: &{Height:1.5 Age:10}
168}
169
170func ExampleValue_FieldByIndex() {
171	// This example shows a case in which the name of a promoted field
172	// is hidden by another field: FieldByName will not work, so
173	// FieldByIndex must be used instead.
174	type user struct {
175		firstName string
176		lastName  string
177	}
178
179	type data struct {
180		user
181		firstName string
182		lastName  string
183	}
184
185	u := data{
186		user:      user{"Embedded John", "Embedded Doe"},
187		firstName: "John",
188		lastName:  "Doe",
189	}
190
191	s := reflect.ValueOf(u).FieldByIndex([]int{0, 1})
192	fmt.Println("embedded last name:", s)
193
194	// Output:
195	// embedded last name: Embedded Doe
196}
197
198func ExampleValue_FieldByName() {
199	type user struct {
200		firstName string
201		lastName  string
202	}
203	u := user{firstName: "John", lastName: "Doe"}
204	s := reflect.ValueOf(u)
205
206	fmt.Println("Name:", s.FieldByName("firstName"))
207	// Output:
208	// Name: John
209}
210