Source file
src/go/types/example_test.go
1
2
3
4
5
6
7
8
9
10 package types_test
11
12
13
14
15
16
17
18 import (
19 "fmt"
20 "go/ast"
21 "go/format"
22 "go/token"
23 "go/types"
24 "log"
25 "regexp"
26 "slices"
27 "strings"
28 )
29
30
31
32 func ExampleScope() {
33
34 fset := token.NewFileSet()
35 var files []*ast.File
36 for _, src := range []string{
37 `package main
38 import "fmt"
39 func main() {
40 freezing := FToC(-18)
41 fmt.Println(freezing, Boiling) }
42 `,
43 `package main
44 import "fmt"
45 type Celsius float64
46 func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) }
47 func FToC(f float64) Celsius { return Celsius(f - 32 / 9 * 5) }
48 const Boiling Celsius = 100
49 func Unused() { {}; {{ var x int; _ = x }} } // make sure empty block scopes get printed
50 `,
51 } {
52 files = append(files, mustParse(fset, src))
53 }
54
55
56
57
58 conf := types.Config{Importer: defaultImporter(fset)}
59 pkg, err := conf.Check("temperature", fset, files, nil)
60 if err != nil {
61 log.Fatal(err)
62 }
63
64
65
66 var buf strings.Builder
67 pkg.Scope().WriteTo(&buf, 0, true)
68 rx := regexp.MustCompile(` 0x[a-fA-F\d]*`)
69 fmt.Println(rx.ReplaceAllString(buf.String(), ""))
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 func ExampleMethodSet() {
107
108 const input = `
109 package temperature
110 import "fmt"
111 type Celsius float64
112 func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) }
113 func (c *Celsius) SetF(f float64) { *c = Celsius(f - 32 / 9 * 5) }
114
115 type S struct { I; m int }
116 type I interface { m() byte }
117 `
118 fset := token.NewFileSet()
119 f := mustParse(fset, input)
120
121
122
123
124 conf := types.Config{Importer: defaultImporter(fset)}
125 pkg, err := conf.Check("temperature", fset, []*ast.File{f}, nil)
126 if err != nil {
127 log.Fatal(err)
128 }
129
130
131 celsius := pkg.Scope().Lookup("Celsius").Type()
132 for _, t := range []types.Type{celsius, types.NewPointer(celsius)} {
133 fmt.Printf("Method set of %s:\n", t)
134 for m := range types.NewMethodSet(t).Methods() {
135 fmt.Println(m)
136 }
137 fmt.Println()
138 }
139
140
141 styp := pkg.Scope().Lookup("S").Type()
142 fmt.Printf("Method set of %s:\n", styp)
143 fmt.Println(types.NewMethodSet(styp))
144
145
146
147
148
149
150
151
152
153
154
155 }
156
157
158
159
160 func ExampleInfo() {
161
162 const input = `
163 package fib
164
165 type S string
166
167 var a, b, c = len(b), S(c), "hello"
168
169 func fib(x int) int {
170 if x < 2 {
171 return x
172 }
173 return fib(x-1) - fib(x-2)
174 }`
175
176
177 fset := token.NewFileSet()
178 f := mustParse(fset, input)
179
180
181
182
183 info := types.Info{
184 Types: make(map[ast.Expr]types.TypeAndValue),
185 Defs: make(map[*ast.Ident]types.Object),
186 Uses: make(map[*ast.Ident]types.Object),
187 }
188 var conf types.Config
189 pkg, err := conf.Check("fib", fset, []*ast.File{f}, &info)
190 if err != nil {
191 log.Fatal(err)
192 }
193
194
195 fmt.Printf("InitOrder: %v\n\n", info.InitOrder)
196
197
198
199 fmt.Println("Defs and Uses of each named object:")
200 usesByObj := make(map[types.Object][]string)
201 for id, obj := range info.Uses {
202 posn := fset.Position(id.Pos())
203 lineCol := fmt.Sprintf("%d:%d", posn.Line, posn.Column)
204 usesByObj[obj] = append(usesByObj[obj], lineCol)
205 }
206 var items []string
207 for obj, uses := range usesByObj {
208 slices.Sort(uses)
209 item := fmt.Sprintf("%s:\n defined at %s\n used at %s",
210 types.ObjectString(obj, types.RelativeTo(pkg)),
211 fset.Position(obj.Pos()),
212 strings.Join(uses, ", "))
213 items = append(items, item)
214 }
215 slices.Sort(items)
216 fmt.Println(strings.Join(items, "\n"))
217 fmt.Println()
218
219 fmt.Println("Types and Values of each expression:")
220 items = nil
221 for expr, tv := range info.Types {
222 var buf strings.Builder
223 posn := fset.Position(expr.Pos())
224 tvstr := tv.Type.String()
225 if tv.Value != nil {
226 tvstr += " = " + tv.Value.String()
227 }
228
229 fmt.Fprintf(&buf, "%2d:%2d | %-19s | %-7s : %s",
230 posn.Line, posn.Column, exprString(fset, expr),
231 mode(tv), tvstr)
232 items = append(items, buf.String())
233 }
234 slices.Sort(items)
235 fmt.Println(strings.Join(items, "\n"))
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 func mode(tv types.TypeAndValue) string {
295 switch {
296 case tv.IsVoid():
297 return "void"
298 case tv.IsType():
299 return "type"
300 case tv.IsBuiltin():
301 return "builtin"
302 case tv.IsNil():
303 return "nil"
304 case tv.Assignable():
305 if tv.Addressable() {
306 return "var"
307 }
308 return "mapindex"
309 case tv.IsValue():
310 return "value"
311 default:
312 return "unknown"
313 }
314 }
315
316 func exprString(fset *token.FileSet, expr ast.Expr) string {
317 var buf strings.Builder
318 format.Node(&buf, fset, expr)
319 return buf.String()
320 }
321
View as plain text