├── LICENSE
├── README.md
├── appengine-hello
├── README.md
├── app.go
├── app.yaml
└── static
│ ├── favicon.ico
│ ├── index.html
│ ├── script.js
│ └── style.css
├── go.mod
├── go.sum
├── gotypes
├── Makefile
├── README.md
├── defsuses
│ └── main.go
├── doc
│ └── main.go
├── go-types.md
├── hello
│ └── hello.go
├── hugeparam
│ └── main.go
├── implements
│ └── main.go
├── lookup
│ └── lookup.go
├── nilfunc
│ └── main.go
├── pkginfo
│ └── main.go
├── skeleton
│ └── main.go
├── typeandvalue
│ └── main.go
└── weave.go
├── hello
└── hello.go
├── outyet
├── Dockerfile
├── containers.yaml
├── main.go
└── main_test.go
├── stringutil
├── reverse.go
└── reverse_test.go
└── template
├── image.tmpl
├── index.tmpl
└── main.go
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Go example projects
2 |
3 | [](https://pkg.go.dev/golang.org/x/example)
4 |
5 | This repository contains a collection of Go programs and libraries that
6 | demonstrate the language, standard libraries, and tools.
7 |
8 | ## Clone the project
9 |
10 | ```
11 | $ git clone https://go.googlesource.com/example
12 | $ cd example
13 | ```
14 | https://go.googlesource.com/example is the canonical Git repository.
15 | It is mirrored at https://github.com/golang/example.
16 | ## [hello](hello/) and [stringutil](stringutil/)
17 |
18 | ```
19 | $ cd hello
20 | $ go build
21 | ```
22 | A trivial "Hello, world" program that uses a stringutil package.
23 |
24 | Command [hello](hello/) covers:
25 |
26 | * The basic form of an executable command
27 | * Importing packages (from the standard library and the local repository)
28 | * Printing strings ([fmt](//golang.org/pkg/fmt/))
29 |
30 | Library [stringutil](stringutil/) covers:
31 |
32 | * The basic form of a library
33 | * Conversion between string and []rune
34 | * Table-driven unit tests ([testing](//golang.org/pkg/testing/))
35 |
36 | ## [outyet](outyet/)
37 |
38 | ```
39 | $ cd outyet
40 | $ go build
41 | ```
42 | A web server that answers the question: "Is Go 1.x out yet?"
43 |
44 | Topics covered:
45 |
46 | * Command-line flags ([flag](//golang.org/pkg/flag/))
47 | * Web servers ([net/http](//golang.org/pkg/net/http/))
48 | * HTML Templates ([html/template](//golang.org/pkg/html/template/))
49 | * Logging ([log](//golang.org/pkg/log/))
50 | * Long-running background processes
51 | * Synchronizing data access between goroutines ([sync](//golang.org/pkg/sync/))
52 | * Exporting server state for monitoring ([expvar](//golang.org/pkg/expvar/))
53 | * Unit and integration tests ([testing](//golang.org/pkg/testing/))
54 | * Dependency injection
55 | * Time ([time](//golang.org/pkg/time/))
56 |
57 | ## [appengine-hello](appengine-hello/)
58 |
59 | A trivial "Hello, world" App Engine application intended to be used as the
60 | starting point for your own code. Please see
61 | [Google App Engine SDK for Go](https://cloud.google.com/appengine/downloads#Google_App_Engine_SDK_for_Go)
62 | and [Quickstart for Go in the App Engine Standard Environment](https://cloud.google.com/appengine/docs/standard/go/quickstart).
63 |
64 | ## [gotypes](gotypes/)
65 |
66 | The `go/types` package is a type-checker for Go programs. It is one of the most
67 | complex packages in Go's standard library, so we have provided this tutorial to
68 | help you find your bearings. It comes with several example programs that you
69 | can obtain using `go get` and play with as you learn to build tools that analyze
70 | or manipulate Go programs.
71 |
72 | ## [template](template/)
73 |
74 | A trivial web server that demonstrates the use of the
75 | [`template` package](https://golang.org/pkg/text/template/)'s `block` feature.
76 |
--------------------------------------------------------------------------------
/appengine-hello/README.md:
--------------------------------------------------------------------------------
1 | This code is a starting point for your Google App Engine application in
2 | Go.
3 |
4 | To run the application locally you need the install the [Go Cloud
5 | SDK](https://cloud.google.com/appengine/docs/go/#Go_tools) and execute the next
6 | command from the directory containing this file:
7 |
8 | $ goapp serve app.yaml
9 |
10 | To deploy the application you have to first create an App Engine project
11 | and use it as the application file in all the yaml files.
12 |
--------------------------------------------------------------------------------
/appengine-hello/app.go:
--------------------------------------------------------------------------------
1 | // Copyright 2015 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // Package hello is a simple App Engine application that replies to requests
16 | // on /hello with a welcoming message.
17 | package hello
18 |
19 | import (
20 | "fmt"
21 | "net/http"
22 | )
23 |
24 | // init is run before the application starts serving.
25 | func init() {
26 | // Handle all requests with path /hello with the helloHandler function.
27 | http.HandleFunc("/hello", helloHandler)
28 | }
29 |
30 | func helloHandler(w http.ResponseWriter, r *http.Request) {
31 | fmt.Fprintln(w, "Hello from the Go app")
32 | }
33 |
--------------------------------------------------------------------------------
/appengine-hello/app.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2015 Google Inc. All rights reserved.
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http:#www.apache.org/licenses/LICENSE-2.0
6 |
7 | # Unless required by applicable law or agreed to writing, software distributed
8 | # under the License is distributed on a "AS IS" BASIS, WITHOUT WARRANTIES OR
9 | # CONDITIONS OF ANY KIND, either express or implied.
10 |
11 | # See the License for the specific language governing permissions and
12 | # limitations under the License.
13 |
14 | application: you-application-id
15 | version: 1
16 | runtime: go
17 | api_version: go1
18 |
19 | handlers:
20 | - url: /hello
21 | script: _go_app
22 |
23 | - url: /favicon.ico
24 | static_files: static/favicon.ico
25 | upload: static/favicon.ico
26 |
27 | - url: /
28 | static_files: static/index.html
29 | upload: static/index.html
30 |
31 | - url: /
32 | static_dir: static
33 |
--------------------------------------------------------------------------------
/appengine-hello/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev050/golangproject/cb55c9ffdcd1647d020e2f1e56a20338f71292a8/appengine-hello/static/favicon.ico
--------------------------------------------------------------------------------
/appengine-hello/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 |
21 |
22 | Hello, world
23 |
24 |
25 |
26 |
27 |
28 |
Hello, world
29 |
30 |
31 |
Click on the button to fetch the message.
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/appengine-hello/static/script.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2015 Google Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | "use strict";
18 |
19 | function fetchMessage() {
20 | var xmlHttp = new XMLHttpRequest();
21 | xmlHttp.open("GET", "/hello", false);
22 | xmlHttp.send(null);
23 | document.getElementById("message").innerHTML = xmlHttp.responseText;
24 | }
--------------------------------------------------------------------------------
/appengine-hello/static/style.css:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2015 Google Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | h1 {
18 | text-align: center;
19 | }
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module golang.org/x/example
2 |
3 | go 1.15
4 |
5 | require golang.org/x/tools v0.0.0-20210112183307-1e6ecd4bf1b0
6 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
2 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
3 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
4 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
5 | golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
6 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
7 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
8 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
9 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
10 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
11 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
12 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
13 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
14 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
15 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
16 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
17 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
18 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
19 | golang.org/x/tools v0.0.0-20210112183307-1e6ecd4bf1b0 h1:iZhiQWrjyEuXG495d9MXkcmhrlxbQyGp0uNBY+YBZDk=
20 | golang.org/x/tools v0.0.0-20210112183307-1e6ecd4bf1b0/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
21 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
22 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
23 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
24 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
25 |
--------------------------------------------------------------------------------
/gotypes/Makefile:
--------------------------------------------------------------------------------
1 |
2 | all: README.md
3 | go build ./...
4 |
5 | README.md: go-types.md weave.go $(wildcard */*.go)
6 | go run weave.go go-types.md >README.md
7 |
8 | # This is for previewing using github.
9 | # $HOME/markdown must be a github client.
10 | test: README.md
11 | cp README.md $$HOME/markdown/
12 | (cd $$HOME/markdown/ && git commit -m . README.md && git push)
13 |
14 |
--------------------------------------------------------------------------------
/gotypes/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # `go/types`: The Go Type Checker
4 |
5 | This document is maintained by Alan Donovan `adonovan@google.com`.
6 |
7 | [October 2015 GothamGo talk on go/types](https://docs.google.com/presentation/d/13OvHYozAUBeISPRoLgG7kMBuja1NsU1D_mMlmbaYojk/view)
8 |
9 |
10 | # Contents
11 |
12 | 1. [Changes in Go 1.18](#changes-in-go-1.18)
13 | 1. [Introduction](#introduction)
14 | 1. [An Example](#an-example)
15 | 1. [Objects](#objects)
16 | 1. [Identifier Resolution](#identifier-resolution)
17 | 1. [Scopes](#scopes)
18 | 1. [Initialization Order](#initialization-order)
19 | 1. [Types](#types)
20 | 1. [Basic types](#basic-types)
21 | 1. [Simple Composite Types](#simple-composite-types)
22 | 1. [Struct Types](#struct-types)
23 | 1. [Tuple Types](#tuple-types)
24 | 1. [Function and Method Types](#function-and-method-types)
25 | 1. [Named Types](#named-types)
26 | 1. [Interface Types](#interface-types)
27 | 1. [TypeAndValue](#typeandvalue)
28 | 1. [Selections](#selections)
29 | 1. [Ids](#ids)
30 | 1. [Method Sets](#method-sets)
31 | 1. [Constants](#constants)
32 | 1. [Size and Alignment](#size-and-alignment)
33 | 1. [Imports](#imports)
34 | 1. [Formatting support](#formatting-support)
35 | 1. [Getting from A to B](#getting-from-a-to-b)
36 |
37 | # Changes in Go 1.18
38 |
39 | Go 1.18 introduces generic Go code, and several corresponding new APIs for
40 | `go/types`. This document is not yet up-to-date for these changes, but a guide
41 | to the new changes exists at
42 | [`x/exp/typeparams/example`](https://github.com/golang/exp/tree/master/typeparams/example).
43 |
44 | # Introduction
45 |
46 |
47 | The [`go/types` package]('https://golang.org/pkg/go/types) is a
48 | type-checker for Go programs, designed by Robert Griesemer.
49 | It became part of Go's standard library in Go 1.5.
50 | Measured by lines of code and by API surface area, it is one of the
51 | most complex packages in Go's standard library, and using it requires
52 | a firm grasp of the structure of Go programs.
53 | This tutorial will help you find your bearings.
54 | It comes with several example programs that you can obtain with `go get` and play with.
55 | We assume you are a proficient Go programmer who wants to build tools
56 | to analyze or manipulate Go programs and that you have some knowledge
57 | of how a typical compiler works.
58 |
59 | The type checker complements several existing
60 | standard packages for analyzing Go programs.
61 | We've listed them below.
62 |
63 |
64 | → go/types
65 | go/constant
66 | go/parser
67 | go/ast
68 | go/scanner
69 | go/token
70 |
71 |
72 | Starting at the bottom, the
73 | [`go/token` package](http://golang.org/pkg/go/token)
74 | defines the lexical tokens of Go.
75 | The [`go/scanner` package](http://golang.org/pkg/go/scanner) tokenizes an input stream and records
76 | file position information for use in diagnostics
77 | or for file surgery in a refactoring tool.
78 | The [`go/ast` package](http://golang.org/pkg/go/ast)
79 | defines the data types of the abstract syntax tree (AST).
80 | The [`go/parser` package](http://golang.org/pkg/go/parser)
81 | provides a robust recursive-descent parser that constructs the AST.
82 | And [`go/constant`](http://golang.org/pkg/go/constant)
83 | provides representations and arithmetic operations for the values of compile-time
84 | constant expressions, as we'll see in
85 | [Constants](#constants).
86 |
87 |
88 |
89 | The [`golang.org/x/tools/go/loader` package](https://pkg.go.dev/golang.org/x/tools/go/loader)
90 | from the `x/tools` repository is a client of the type
91 | checker that loads, parses, and type-checks a complete Go program from
92 | source code.
93 | We use it in some of our examples and you may find it useful too.
94 |
95 |
96 |
97 | The Go type checker does three main things.
98 | First, for every name in the program, it determines which declaration
99 | the name refers to; this is known as _identifier resolution_.
100 | Second, for every expression in the program, it determines what type
101 | that expression has, or reports an error if the expression has no
102 | type, or has an inappropriate type for its context; this is known as
103 | _type deduction_.
104 | Third, for every constant expression in the program, it determines the
105 | value of that constant; this is known as _constant evaluation_.
106 |
107 |
108 |
109 | Superficially, it appears that these three processes could be done
110 | sequentially, in the order above, but perhaps surprisingly, they must
111 | be done together.
112 | For example, the value of a constant may depend on the type of an
113 | expression due to operators like `unsafe.Sizeof`.
114 | Conversely, the type of an expression may depend on the value of a
115 | constant, since array types contain constants.
116 | As a result, type deduction and constant evaluation must be done
117 | together.
118 |
119 |
120 |
121 | As another example, we cannot resolve the identifier `k` in the composite
122 | literal `T{k: 0}` until we know whether `T` is a struct type.
123 | If it is, then `k` must be found among `T`'s fields.
124 | If not, then `k` is an ordinary reference
125 | to a constant or variable in the lexical environment.
126 | Consequently, identifier resolution and type deduction are also
127 | inseparable in the general case.
128 |
129 |
130 |
131 | Nonetheless, the three processes of identifier resolution, type
132 | deduction, and constant evaluation can be separated for the purpose of
133 | explanation.
134 |
135 |
136 | # An Example
137 |
138 |
139 | The code below shows the most basic use of the type checker to check
140 | the _hello, world_ program, supplied as a string.
141 | Later examples will be variations on this one, and we'll often omit
142 | boilerplate details such as parsing.
143 | To check out and build the examples,
144 | run `go get golang.org/x/example/gotypes/...`.
145 |
146 |
147 | // go get golang.org/x/example/gotypes/pkginfo
148 |
149 | ```
150 | package main
151 |
152 | import (
153 | "fmt"
154 | "go/ast"
155 | "go/importer"
156 | "go/parser"
157 | "go/token"
158 | "go/types"
159 | "log"
160 | )
161 |
162 | const hello = `package main
163 |
164 | import "fmt"
165 |
166 | func main() {
167 | fmt.Println("Hello, world")
168 | }`
169 |
170 | func main() {
171 | fset := token.NewFileSet()
172 |
173 | // Parse the input string, []byte, or io.Reader,
174 | // recording position information in fset.
175 | // ParseFile returns an *ast.File, a syntax tree.
176 | f, err := parser.ParseFile(fset, "hello.go", hello, 0)
177 | if err != nil {
178 | log.Fatal(err) // parse error
179 | }
180 |
181 | // A Config controls various options of the type checker.
182 | // The defaults work fine except for one setting:
183 | // we must specify how to deal with imports.
184 | conf := types.Config{Importer: importer.Default()}
185 |
186 | // Type-check the package containing only file f.
187 | // Check returns a *types.Package.
188 | pkg, err := conf.Check("cmd/hello", fset, []*ast.File{f}, nil)
189 | if err != nil {
190 | log.Fatal(err) // type error
191 | }
192 |
193 | fmt.Printf("Package %q\n", pkg.Path())
194 | fmt.Printf("Name: %s\n", pkg.Name())
195 | fmt.Printf("Imports: %s\n", pkg.Imports())
196 | fmt.Printf("Scope: %s\n", pkg.Scope())
197 | }
198 | ```
199 |
200 |
201 | First, the program creates a
202 | [`token.FileSet`](http://golang.org/pkg/go/token/#FileSet).
203 | To avoid the need to store file names and line and column
204 | numbers in every node of the syntax tree, the `go/token` package
205 | provides `FileSet`, a data structure that stores this information
206 | compactly for a sequence of files.
207 | A `FileSet` records each file name only once, and records
208 | only the byte offsets of each newline, allowing a position within
209 | any file to be identified using a small integer called a
210 | `token.Pos`.
211 | Many tools create a single `FileSet` at startup.
212 | Any part of the program that needs to convert a `token.Pos` into
213 | an intelligible location---as part of an error message, for
214 | instance---must have access to the `FileSet`.
215 |
216 |
217 |
218 | Second, the program parses the input string.
219 | More realistic packages contain several source files, so the parsing
220 | step must be repeated for each one, or better, done in parallel.
221 | Third, it creates a `Config` that specifies type-checking options.
222 | Since the _hello, world_ program uses imports, we must indicate
223 | how to locate the imported packages.
224 | Here we use `importer.Default()`, which loads compiler-generated
225 | export data, but we'll explore alternatives in [Imports](#imports).
226 |
227 |
228 |
229 | Fourth, the program calls `Check`.
230 | This creates a `Package` whose path is `"cmd/hello"`, and
231 | type-checks each of the specified files---just one in this example.
232 | The final (nil) argument is a pointer to an optional `Info`
233 | struct that returns additional deductions from the type checker; more
234 | on that later.
235 | `Check` returns a `Package` even when it also returns an error.
236 | The type checker is robust to ill-formed input,
237 | and goes to great lengths to report accurate
238 | partial information even in the vicinity of syntax or type errors.
239 | `Package` has this definition:
240 |
241 |
242 | type Package struct{ ... }
243 | func (*Package) Path() string
244 | func (*Package) Name() string
245 | func (*Package) Scope() *Scope
246 | func (*Package) Imports() []*Package
247 |
248 |
249 | Finally, the program prints the attributes of the package, shown below.
250 | (The hexadecimal number may vary from one run to the next.)
251 |
252 |
253 | ```
254 | $ go build golang.org/x/example/gotypes/pkginfo
255 | $ ./pkginfo
256 | Package "cmd/hello"
257 | Name: main
258 | Imports: [package fmt ("fmt")]
259 | Scope: package "cmd/hello" scope 0x820533590 {
260 | . func cmd/hello.main()
261 | }
262 | ```
263 |
264 |
265 | A package's `Path`, such as `"encoding/json"`, is the string
266 | by which import declarations identify it.
267 | It is unique within a `$GOPATH` workspace,
268 | and for published packages it must be globally unique.
269 |
270 |
271 | A package's `Name` is the identifier in the `package`
272 | declaration of each source file within the package, such as `json`.
273 | The type checker reports an error if not all the package declarations in
274 | the package agree.
275 | The package name determines how the package is known when it is
276 | imported into a file (unless a renaming import is used),
277 | but is otherwise not visible to a program.
278 |
279 |
280 | `Scope` returns the package's [_lexical block_](#scopes),
281 | which provides access to all the named entities or
282 | [_objects_](#objects) declared at package level.
283 | `Imports` returns the set of packages directly imported by this
284 | one, and may be useful for computing dependencies
285 | ([Initialization Order](#initialization-order)).
286 |
287 |
288 |
289 | # Objects
290 |
291 |
292 | The task of identifier resolution is to map every identifier in the
293 | syntax tree, that is, every `ast.Ident`, to an object.
294 | For our purposes, an _object_ is a named entity created by a
295 | declaration, such as a `var`, `type`, or `func`
296 | declaration.
297 | (This is different from the everyday meaning of object in
298 | object-oriented programming.)
299 |
300 |
301 |
302 | Objects are represented by the `Object` interface:
303 |
304 |
305 | type Object interface {
306 | Name() string // package-local object name
307 | Exported() bool // reports whether the name starts with a capital letter
308 | Type() Type // object type
309 | Pos() token.Pos // position of object identifier in declaration
310 |
311 | Parent() *Scope // scope in which this object is declared
312 | Pkg() *Package // nil for objects in the Universe scope and labels
313 | Id() string // object id (see Ids section below)
314 | }
315 |
316 |
317 | The first four methods are straightforward; we'll explain the other
318 | three later.
319 | `Name` returns the object's name---an identifier.
320 | `Exported` is a convenience method that reports whether the first
321 | letter of `Name` is a capital, indicating that the object may be
322 | visible from outside the package.
323 | It's a shorthand for `ast.IsExported(obj.Name())`.
324 | `Type` returns the object's type; we'll come back to that in
325 | [Types](#types).
326 |
327 |
328 |
329 | `Pos` returns the source position of the object's declaring identifier.
330 | To make sense of a `token.Pos`, we need to call the
331 | `(*token.FileSet).Position` method, which returns a struct with
332 | individual fields for the file name, line number, column, and byte
333 | offset, though usually we just call its `String` method:
334 |
335 |
336 | fmt.Println(fset.Position(obj.Pos())) // "hello.go:10:6"
337 |
338 |
339 | Not all objects carry position information.
340 | Since the file format for compiler export data ([Imports](#imports))
341 | does not record position information, calling `Pos` on an object
342 | imported from such a file returns zero, also known as
343 | `token.NoPos`.
344 |
345 |
346 |
347 | There are eight kinds of objects in the Go type checker.
348 | Most familiar are the kinds that can be declared at package level:
349 | constants, variables, functions, and types.
350 | Less familiar are statement labels, imported package names
351 | (such as `json` in a file containing an `import "encoding/json"`
352 | declaration), built-in functions (such as `append` and
353 | `len`), and the pre-declared `nil`.
354 | The eight types shown below are the only concrete types that satisfy
355 | the `Object` interface.
356 | In other words, `Object` is a _discriminated union_ of 8
357 | possible types, and we commonly use a type switch to distinguish them.
358 |
359 |
360 | Object = *Func // function, concrete method, or abstract method
361 | | *Var // variable, parameter, result, or struct field
362 | | *Const // constant
363 | | *TypeName // type name
364 | | *Label // statement label
365 | | *PkgName // package name, e.g. json after import "encoding/json"
366 | | *Builtin // predeclared function such as append or len
367 | | *Nil // predeclared nil
368 |
369 |
370 | `Object`s are canonical.
371 | That is, two `Object`s `x` and `y` denote the same
372 | entity if and only if `x==y`.
373 | Object identity is significant, and objects are routinely compared by
374 | the addresses of the underlying pointers.
375 | Although a package-level object is uniquely identified by its name
376 | and enclosing package, for other objects there is no simple way to
377 | obtain a string that uniquely identifies it.
378 |
379 |
380 |
381 | The `Parent` method returns the `Scope` (lexical block) in
382 | which the object was declared; we'll come back to this in
383 | [Scopes](#scopes).
384 | Fields and methods are not found in the lexical environment, so
385 | their objects have no `Parent`.
386 |
387 |
388 |
389 |
390 | The `Pkg` method returns the `Package` to which this object
391 | belongs, even for objects not declared at package level.
392 | Only predeclared objects have no package.
393 | The `Id` method will be explained in [Ids](#ids).
394 |
395 |
396 |
397 | Not all methods make sense for each kind of object. For instance,
398 | the last four kinds above have no meaningful `Type` method.
399 | And some kinds of objects have methods in addition to those required by the
400 | `Object` interface:
401 |
402 |
403 | func (*Func) Scope() *Scope
404 | func (*Var) Anonymous() bool
405 | func (*Var) IsField() bool
406 | func (*Const) Val() constant.Value
407 | func (*TypeName) IsAlias() bool
408 | func (*PkgName) Imported() *Package
409 |
410 |
411 | `(*Func).Scope` returns the [lexical block](#scopes)
412 | containing the function's parameters, results,
413 | and other local declarations.
414 | `(*Var).IsField` distinguishes struct fields from ordinary
415 | variables, and `(*Var).Anonymous` discriminates named fields like
416 | the one in `struct{T T}` from anonymous fields like the one in `struct{T}`.
417 | `(*Const).Val` returns the value of a named [constant](#constants).
418 |
419 |
420 | `(*TypeName).IsAlias`, introduced in Go 1.9, reports whether the
421 | type name is simply an alias for a type (as in `type I = int`),
422 | as opposed to a definition of a [`Named`](#named-types) type, as
423 | in `type Celsius float64`.
424 |
425 |
426 | `(*PkgName).Imported` returns the package (for instance,
427 | `encoding/json`) denoted by a given import name such as `json`.
428 | Each time a package is imported, a new `PkgName` object is
429 | created, usually with the same name as the `Package` it
430 | denotes, but not always, as in the case of a renaming import.
431 | `PkgName`s are objects, but `Package`s are not.
432 | We'll look more closely at this in [Imports](#imports).
433 |
434 |
435 |
436 | All relationships between the syntax trees (`ast.Node`s) and type
437 | checker data structures such as `Object`s and `Type`s are
438 | stored in mappings outside the syntax tree itself.
439 | Be aware that the `go/ast` package also defines a type called
440 | `Object` that resembles---and predates---the type checker's
441 | `Object`, and that `ast.Object`s are held directly by
442 | identifiers in the AST.
443 | They are created by the parser, which has a necessarily limited view
444 | of the package, so the information they represent is at best partial and
445 | in some cases wrong, as in the `T{k: 0}` example mentioned above.
446 | If you are using the type checker, there is no reason to use the older
447 | `ast.Object` mechanism.
448 |
449 |
450 |
451 | # Identifier Resolution
452 |
453 |
454 | Identifier resolution computes the relationship between
455 | identifiers and objects.
456 | Its results are recorded in the `Info` struct optionally passed
457 | to `Check`.
458 | The fields related to identifier resolution are shown below.
459 |
460 |
461 | type Info struct {
462 | Defs map[*ast.Ident]Object
463 | Uses map[*ast.Ident]Object
464 | Implicits map[ast.Node]Object
465 | Selections map[*ast.SelectorExpr]*Selection
466 | Scopes map[ast.Node]*Scope
467 | ...
468 | }
469 |
470 |
471 | Since not all facts computed by the type checker are needed by every
472 | client, the API lets clients control which components of the result
473 | should be recorded and which discarded: only fields that hold a
474 | non-nil map will be populated during the call to `Check`.
475 |
476 |
477 |
478 | The two fields of type `map[*ast.Ident]Object` are the most important:
479 | `Defs` records _declaring_ identifiers and
480 | `Uses` records _referring_ identifiers.
481 | In the example below, the comments indicate which identifiers are of
482 | which kind.
483 |
484 |
485 | var x int // def of x, use of int
486 | fmt.Println(x) // uses of fmt, Println, and x
487 | type T struct{U} // def of T, use of U (type), def of U (field)
488 |
489 |
490 | The final line above illustrates why we don't combine `Defs` and
491 | `Uses` into one map.
492 | In the anonymous field declaration `struct{U}`, the
493 | identifier `U` is both a use of the type `U` (a
494 | `TypeName`) and a definition of the anonymous field (a
495 | `Var`).
496 |
497 |
498 |
499 | The function below prints the location of each referring and defining
500 | identifier in the input program, and the object it refers to.
501 |
502 |
503 | // go get golang.org/x/example/gotypes/defsuses
504 |
505 | ```
506 | func PrintDefsUses(fset *token.FileSet, files ...*ast.File) error {
507 | conf := types.Config{Importer: importer.Default()}
508 | info := &types.Info{
509 | Defs: make(map[*ast.Ident]types.Object),
510 | Uses: make(map[*ast.Ident]types.Object),
511 | }
512 | _, err := conf.Check("hello", fset, files, info)
513 | if err != nil {
514 | return err // type error
515 | }
516 |
517 | for id, obj := range info.Defs {
518 | fmt.Printf("%s: %q defines %v\n",
519 | fset.Position(id.Pos()), id.Name, obj)
520 | }
521 | for id, obj := range info.Uses {
522 | fmt.Printf("%s: %q uses %v\n",
523 | fset.Position(id.Pos()), id.Name, obj)
524 | }
525 | return nil
526 | }
527 | ```
528 |
529 |
530 | Let's use the _hello, world_ program again as the input:
531 |
532 |
533 | // go get golang.org/x/example/gotypes/hello
534 |
535 | ```
536 | package main
537 |
538 | import "fmt"
539 |
540 | func main() {
541 | fmt.Println("Hello, 世界")
542 | }
543 | ```
544 |
545 |
546 | This is what it prints:
547 |
548 |
549 | ```
550 | $ go build golang.org/x/example/gotypes/defsuses
551 | $ ./defsuses
552 | hello.go:1:9: "main" defines
553 | hello.go:5:6: "main" defines func hello.main()
554 | hello.go:6:9: "fmt" uses package fmt
555 | hello.go:6:13: "Println" uses func fmt.Println(a ...interface{}) (n int, err error)
556 | ```
557 |
558 |
559 | Notice that the `Defs` mapping may contain nil entries in a few
560 | cases.
561 | The first line of output reports that the package identifier
562 | `main` is present in the `Defs` mapping, but has no
563 | associated object.
564 |
565 |
566 |
567 | The `Implicits` mapping handles two cases of the syntax in
568 | which an `Object` is declared without an `ast.Ident`, namely type
569 | switches and import declarations.
570 |
574 | In the type switch below, which declares a local variable `y`,
575 | the type of `y` is different in each case of the switch:
576 |
577 |
578 | switch y := x.(type) {
579 | case int:
580 | fmt.Printf("%d", y)
581 | case string:
582 | fmt.Printf("%q", y)
583 | default:
584 | fmt.Print(y)
585 | }
586 |
587 |
588 | To represent this, for each single-type case, the type checker creates
589 | a separate `Var` object for `y` with the appropriate type,
590 | and `Implicits` maps each `ast.CaseClause` to the `Var`
591 | for that case.
592 | The `default` case, the `nil` case, and cases with more than one
593 | type all use the regular `Var` object that is associated with the
594 | identifier `y`, which is found in the `Defs` mapping.
595 |
596 |
597 |
598 | The import declaration below defines the name `json` without an
599 | `ast.Ident`:
600 |
601 |
602 | import "encoding/json"
603 |
604 |
605 | `Implicits` maps this `ast.ImportSpec` to the `PkgName`
606 | object named `json` that it implicitly declares.
607 |
608 |
609 |
610 | The `Selections` mapping, of type
611 | `map[*ast.SelectorExpr]*Selection`, records the meaning of each
612 | expression of the form _`expr`_`.f`, where _`expr`_ is
613 | an expression or type and `f` is the name of a field or method.
614 | These expressions, called _selections_, are represented by
615 | `ast.SelectorExpr` nodes in the AST.
616 | We'll talk more about the `Selection` type in [Selections](#selections).
617 |
618 |
619 |
620 | Not all `ast.SelectorExpr` nodes represent selections.
621 | Expressions like `fmt.Println`, in which a package name precedes
622 | the dot, are _qualified identifiers_.
623 | They do not appear in the `Selections` mapping, but their
624 | constituent identifiers (such as `fmt` and `Println`) both
625 | appear in `Uses`.
626 |
627 |
628 |
629 | Referring identifiers that are not part of an `ast.SelectorExpr`
630 | are _lexical references_.
631 | That is, they are resolved to an object by searching for the
632 | innermost enclosing lexical declaration of that name.
633 | We'll see how that search works in the next section.
634 |
635 |
636 | # Scopes
637 |
638 |
639 | The `Scope` type is a mapping from names to objects.
640 |
641 |
642 | type Scope struct{ ... }
643 |
644 | func (s *Scope) Names() []string
645 | func (s *Scope) Lookup(name string) Object
646 |
647 |
648 | `Names` returns the set of names in the mapping, in sorted order.
649 | (It is not a simple accessor though, so call it sparingly.)
650 | The `Lookup ` method returns the object for a given name, so we
651 | can print all the entries or _bindings_ in a scope like this:
652 |
653 |
654 | for _, name := range scope.Names() {
655 | fmt.Println(scope.Lookup(name))
656 | }
657 |
658 |
659 | The _scope_ of a declaration of a name is the region of
660 | program source in which a reference to the name resolves to that
661 | declaration. That is, scope is a property of a declaration.
662 | However, in the `go/types` API, the `Scope` type represents
663 | a _lexical block_, which is one component of the lexical
664 | environment.
665 | Consider the _hello, world_ program again:
666 |
667 |
668 | package main
669 |
670 | import "fmt"
671 |
672 | func main() {
673 | const message = "hello, world"
674 | fmt.Println(message)
675 | }
676 |
677 |
678 | There are four lexical blocks in this program.
679 | The outermost one is the _universe block_, which maps the
680 | pre-declared names like `int`, `true`, and `append` to
681 | their objects---a `TypeName`, a `Const`, and a
682 | `Builtin`, respectively.
683 | The universe block is represented by the global variable
684 | `Universe`, of type `*Scope`, although it's logically a
685 | constant so you shouldn't modify it.
686 |
687 |
688 |
689 | Next is the _package block_, which maps `"main"` to the
690 | `main` function.
691 | Following that is the _file block_, which maps `"fmt"` to
692 | the `PkgName` object for this import of the `fmt` package.
693 | And finally, the innermost block is that of function `main`, a
694 | local block, which contains the declaration of `message`, a `Const`.
695 | The `main` function is trivial, but many functions contain
696 | several blocks since each `if`, `for`, `switch`,
697 | `case`, or `select` statement creates at least one
698 | additional block.
699 | Local blocks nest to arbitrary depths.
700 |
701 |
702 |
703 | The structure of the lexical environment thus forms a tree, with the
704 | universe block at the root, the package blocks beneath it, the file
705 | blocks beneath them, and then any number of local blocks beneath the
706 | files.
707 | We can access and navigate this tree structure with the following
708 | methods of `Scope`:
709 |
710 |
711 | func (s *Scope) Parent() *Scope
712 | func (s *Scope) NumChildren() int
713 | func (s *Scope) Child(i int) *Scope
714 |
715 |
716 | `Parent` lets us walk up the tree, and `Child`
717 | lets us walk down it.
718 | Note that although the `Parent` of every package `Scope` is
719 | `Universe`, `Universe` has no children.
720 | This asymmetry is a consequence of using a global variable to hold
721 | `Universe`.
722 |
723 |
724 |
725 | To obtain the universe block, we use the `Universe` global variable.
726 | To obtain the lexical block of a `Package`, we call its
727 | `Scope` method.
728 | To obtain the scope of a file (`*ast.File`), or any smaller piece
729 | of syntax such as an `*ast.IfStmt`, we consult the `Scopes`
730 | mapping in the `Info` struct, which maps each block-creating
731 | syntax node to its block.
732 | The lexical block of a named function or method can also be obtained
733 | by calling its `(*Func).Scope` method.
734 |
735 |
736 |
741 |
742 |
743 | To look up a name in the lexical environment, we must search the tree
744 | of lexical blocks, starting at a particular `Scope` and walking
745 | up to the root until a declaration of the name is found.
746 | For convenience, the `LookupParent` method does this, returning
747 | not just the object, if found, but also the `Scope` in which it was
748 | declared, which may be an ancestor of the initial one:
749 |
750 |
751 | func (s *Scope) LookupParent(name string, pos token.Pos) (*Scope, Object)
752 |
753 |
754 | The `pos` parameter determines the position in the source code at
755 | which the name should be resolved.
756 | The effective lexical environment is different at each point in the
757 | block because it depends on which local declarations appear
758 | before or after that point.
759 | (We'll see an illustration in a moment.)
760 |
761 |
762 |
763 | `Scope` has several other methods relating to source positions:
764 |
765 |
766 | func (s *Scope) Pos() token.Pos
767 | func (s *Scope) End() token.Pos
768 | func (s *Scope) Contains(pos token.Pos) bool
769 | func (s *Scope) Innermost(pos token.Pos) *Scope
770 |
771 |
772 | `Pos` and `End` report the `Scope`'s start and end
773 | position which, for explicit blocks, coincide with its curly
774 | braces.
775 | `Contains` is a convenience method that reports whether a
776 | position lies in this interval.
777 | `Innermost` returns the innermost scope containing the specified
778 | position, which may be a child or other descendent of the initial
779 | scope.
780 |
781 |
782 |
783 | These features are useful for tools that wish to resolve names or
784 | evaluate constant expressions as if they had appeared at a particular
785 | point within the program.
786 | The next example program finds all the comments in the input,
787 | treating the contents of each one as a name. It looks up each name in
788 | the environment at the position of the comment, and prints what it
789 | finds.
790 | Observe that the `ParseComments` flag directs the parser to
791 | preserve comments in the input.
792 |
793 |
794 | // go get golang.org/x/example/gotypes/lookup
795 |
796 | ```
797 | func main() {
798 | fset := token.NewFileSet()
799 | f, err := parser.ParseFile(fset, "hello.go", hello, parser.ParseComments)
800 | if err != nil {
801 | log.Fatal(err) // parse error
802 | }
803 |
804 | conf := types.Config{Importer: importer.Default()}
805 | pkg, err := conf.Check("cmd/hello", fset, []*ast.File{f}, nil)
806 | if err != nil {
807 | log.Fatal(err) // type error
808 | }
809 |
810 | // Each comment contains a name.
811 | // Look up that name in the innermost scope enclosing the comment.
812 | for _, comment := range f.Comments {
813 | pos := comment.Pos()
814 | name := strings.TrimSpace(comment.Text())
815 | fmt.Printf("At %s,\t%q = ", fset.Position(pos), name)
816 | inner := pkg.Scope().Innermost(pos)
817 | if _, obj := inner.LookupParent(name, pos); obj != nil {
818 | fmt.Println(obj)
819 | } else {
820 | fmt.Println("not found")
821 | }
822 | }
823 | }
824 | ```
825 |
826 |
827 | The expression `pkg.Scope().Innermost(pos)` finds the innermost
828 | `Scope` that encloses the comment, and `LookupParent(name, pos)`
829 | does a name lookup at a specific position in that lexical block.
830 |
831 |
832 |
833 | A typical input is shown below.
834 | The first comment causes a lookup of `"append"` in the file block.
835 | The second comment looks up `"fmt"` in the `main` function's block,
836 | and so on.
837 |
838 |
839 | ```
840 | const hello = `
841 | package main
842 |
843 | import "fmt"
844 |
845 | // append
846 | func main() {
847 | // fmt
848 | fmt.Println("Hello, world")
849 | // main
850 | main, x := 1, 2
851 | // main
852 | print(main, x)
853 | // x
854 | }
855 | // x
856 | `
857 | ```
858 |
859 |
860 | Here's the output:
861 |
862 |
863 | ```
864 | $ go build golang.org/x/example/gotypes/lookup
865 | $ ./lookup
866 | At hello.go:6:1, "append" = builtin append
867 | At hello.go:8:9, "fmt" = package fmt
868 | At hello.go:10:9, "main" = func cmd/hello.main()
869 | At hello.go:12:9, "main" = var main int
870 | At hello.go:14:9, "x" = var x int
871 | At hello.go:16:1, "x" = not found
872 | ```
873 |
874 |
875 | Notice how the two lookups of `main` return different results,
876 | even though they occur in the same block, because one precedes the
877 | declaration of the local variable named `main` and the other
878 | follows it.
879 | Also notice that there are two lookups of the name `x` but only
880 | the first one, in the function block, succeeds.
881 |
882 |
883 |
884 | Download the program and modify both the input program and
885 | the set of comments to get a better feel for how name resolution works.
886 |
887 |
888 |
889 | The table below summarizes which kinds of objects may be declared at
890 | each level of the tree of lexical blocks.
891 |
892 |
893 | Universe File Package Local
894 | Builtin ✔
895 | Nil ✔
896 | Const ✔ ✔ ✔
897 | TypeName ✔ ✔ ✔
898 | Func ✔
899 | Var ✔ ✔
900 | PkgName ✔
901 | Label ✔
902 |
903 |
904 | # Initialization Order
905 |
906 |
907 | In the course of identifier resolution, the type checker constructs a
908 | graph of references among declarations of package-level variables and
909 | functions.
910 | The type checker reports an error if the initializer expression for a
911 | variable refers to that variable, whether directly or indirectly.
912 |
913 |
914 |
915 | The reference graph determines the initialization order of the
916 | package-level variables, as required by the Go spec, using a
917 | breadth-first algorithm.
918 | First, variables in the graph with no successors are removed, sorted
919 | into the order in which they appear in the source code, then added
920 | to a list. This creates more variables that have no successors.
921 | The process repeats until they have all been removed.
922 |
923 |
924 |
925 | The result is available in the `InitOrder` field of the
926 | `Info` struct, whose type is `[]Initializer`.
927 |
928 |
929 | type Info struct {
930 | ...
931 | InitOrder []Initializer
932 | ...
933 | }
934 |
935 | type Initializer struct {
936 | Lhs []*Var // var Lhs = Rhs
937 | Rhs ast.Expr
938 | }
939 |
940 |
941 | Each element of the list represents a single initializer expression
942 | that must be executed, and the variables to which it is assigned.
943 | The variables may number zero, one, or more, as in these examples:
944 |
945 |
946 | var _ io.Writer = new(bytes.Buffer)
947 | var rx = regexp.MustCompile("^b(an)*a$")
948 | var cwd, cwdErr = os.Getwd()
949 |
950 |
951 | This process governs the initialization order of variables within a
952 | package.
953 | Across packages, dependencies must be initialized first, although the
954 | order among them is not specified.
955 | That is, any topological order of the import graph will do.
956 | The `(*Package).Imports` method returns the set of direct
957 | dependencies of a package.
958 |
959 |
960 | # Types
961 |
962 |
963 | The main job of the type checker is, of course, to deduce the type
964 | of each expression and to report type errors.
965 | Like `Object`, `Type` is an interface type used as a
966 | discriminated union of several concrete types but, unlike
967 | `Object`, `Type` has very few methods because types have
968 | little in common with each other.
969 | Here is the interface:
970 |
971 |
972 | type Type interface {
973 | Underlying() Type
974 | }
975 |
976 |
977 | And here are the eleven concrete types that satisfy it:
978 |
979 |
980 | Type = *Basic
981 | | *Pointer
982 | | *Array
983 | | *Slice
984 | | *Map
985 | | *Chan
986 | | *Struct
987 | | *Tuple
988 | | *Signature
989 | | *Named
990 | | *Interface
991 |
992 |
993 | With the exception of `Named` types, instances of `Type` are
994 | not canonical.
995 | That is, it is usually a mistake to compare types using `t1==t2`
996 | since this equivalence is not the same as the
997 | [type identity relation](https://golang.org/ref/spec#Type_identity)
998 | defined by the Go spec.
999 | Use this function instead:
1000 |
1001 |
1002 | func Identical(t1, t2 Type) bool
1003 |
1004 |
1005 | For the same reason, you should not use a `Type` as a key in a map.
1006 | The [`golang.org/x/tools/go/types/typeutil` package](https://pkg.go.dev/golang.org/x/tools/go/types/typeutil)
1007 | provides a map keyed by types that uses the correct
1008 | equivalence relation.
1009 |
1010 |
1011 | The Go spec defines three relations over types.
1012 | [_Assignability_](https://golang.org/ref/spec#Assignability)
1013 | governs which pairs of types may appear on the
1014 | left- and right-hand side of an assignment, including implicit
1015 | assignments such as function calls, map and channel operations, and so
1016 | on.
1017 | [_Comparability_](https://golang.org/ref/spec#Comparison_operators)
1018 | determines which types may appear in a comparison `x==y` or a
1019 | switch case or may be used as a map key.
1020 | [_Convertibility_](https://golang.org/ref/spec#Conversions)
1021 | governs which pairs of types are allowed in a conversion operation
1022 | `T(v)`.
1023 | You can query these relations with the following predicate functions:
1024 |
1025 |
1026 | func AssignableTo(V, T Type) bool
1027 | func Comparable(T Type) bool
1028 | func ConvertibleTo(V, T Type) bool
1029 |
1030 |
1031 | Let's take a look at each kind of type.
1032 |
1033 |
1034 | ## Basic types
1035 |
1036 |
1037 | `Basic` represents all types that are not composed from simpler
1038 | types.
1039 | This is essentially the set of underlying types that a constant expression is
1040 | permitted to have--strings, booleans, and numbers---but it also
1041 | includes `unsafe.Pointer` and untyped nil.
1042 |
1043 |
1044 | type Basic struct{...}
1045 | func (*Basic) Kind() BasicKind
1046 | func (*Basic) Name() string
1047 | func (*Basic) Info() BasicInfo
1048 |
1049 |
1050 | The `Kind` method returns an "enum" value that indicates which
1051 | basic type this is.
1052 | The kinds `Bool`, `String`, `Int16`, and so on,
1053 | represent the corresponding predeclared boolean, string, or numeric
1054 | types.
1055 | There are two synonyms: `Byte` is equivalent to `Uint8`
1056 | and `Rune` is equivalent to `Int32`.
1057 | The kind `UnsafePointer` represents `unsafe.Pointer`.
1058 | The kinds `UntypedBool`, `UntypedInt` and so on represent
1059 | the six kinds of "untyped" constant types: boolean, integer, rune,
1060 | float, complex, and string.
1061 | The kind `UntypedNil` represents the type of the predeclared
1062 | `nil` value.
1063 | And the kind `Invalid` indicates the invalid type, which is used
1064 | for expressions containing errors, or for objects without types, like
1065 | `Label`, `Builtin`, or `PkgName`.
1066 |
1067 |
1068 |
1069 | The `Name` method returns the name of the type, such as
1070 | `"float64"`, and the `Info` method returns a bitfield that
1071 | encodes information about the type, such as whether it is signed or
1072 | unsigned, integer or floating point, or real or complex.
1073 |
1074 |
1075 |
1076 | `Typ` is a table of canonical basic types, indexed by
1077 | kind, so `Typ[String]` returns the `*Basic` that represents
1078 | `string`, for instance.
1079 | Like `Universe`, `Typ` is logically a constant, so don't
1080 | modify it.
1081 |
1082 |
1083 |
1084 | A few minor subtleties:
1085 | According to the Go spec, pre-declared types such as `int` are
1086 | named types for the purposes of assignability, even though the type
1087 | checker does not represent them using `Named`.
1088 | And `unsafe.Pointer` is a pointer type for the purpose of
1089 | determining whether the receiver type of a method is legal, even
1090 | though the type checker does not represent it using `Pointer`.
1091 |
1092 |
1093 |
1094 | The "untyped" types are usually only ascribed to constant expressions,
1095 | but there is one exception.
1096 | A comparison `x==y` has type "untyped bool", so the result of
1097 | this expression may be assigned to a variable of type `bool` or
1098 | any other named boolean type.
1099 |
1100 |
1101 |
1102 | ## Simple Composite Types
1103 |
1104 |
1105 | The types `Pointer`, `Array`, `Slice`, `Map`,
1106 | and `Chan` are pretty self-explanatory.
1107 | All have an `Elem` method that returns the element type `T`
1108 | for a pointer `*T`, an array `[n]T`, a slice `[]T`, a
1109 | map `map[K]T`, or a channel `chan T`.
1110 | This should feel familiar if you've used the `reflect.Value` API.
1111 |
1112 |
1113 |
1114 | In addition, the `*Map`, `*Chan`, and `*Array` types
1115 | have accessor methods that return their key type, direction, and
1116 | length, respectively:
1117 |
1118 |
1119 | func (*Map) Key() Type
1120 | func (*Chan) Dir() ChanDir // = Send | Recv | SendRecv
1121 | func (*Array) Len() int64
1122 |
1123 |
1124 |
1125 | ## Struct Types
1126 |
1127 |
1128 | A struct type has an ordered list of fields and a corresponding
1129 | ordered list of field tags.
1130 |
1131 |
1132 | type Struct struct{ ... }
1133 | func (*Struct) NumFields() int
1134 | func (*Struct) Field(i int) *Var
1135 | func (*Struct) Tag(i int) string
1136 |
1137 |
1138 | Each field is a `Var` object whose `IsField` method returns true.
1139 | Field objects have no `Parent` scope, because they are
1140 | resolved through selections, not through the lexical environment.
1141 |
1142 |
1143 |
1144 |
1145 | Thanks to embedding, the expression `new(S).f` may be a shorthand
1146 | for a longer expression such as `new(S).d.e.f`, but in the
1147 | representation of `Struct` types, these field selection
1148 | operations are explicit.
1149 | That is, the set of fields of struct type `S` does not include `f`.
1150 | An anonymous field is represented like a regular field, but its
1151 | `Anonymous` method returns true.
1152 |
1153 |
1154 |
1155 | One subtlety is relevant to tools that generate documentation.
1156 | When analyzing a declaration such as this,
1157 |
1158 |
1159 | type T struct{x int}
1160 |
1161 |
1162 | it may be tempting to consider the `Var` object for field `x` as if it
1163 | had the name `"T.x"`, but beware: field objects do not have
1164 | canonical names and there is no way to obtain the name `"T"`
1165 | from the `Var` for `x`.
1166 | That's because several types may have the same underlying struct type,
1167 | as in this code:
1168 |
1169 |
1170 | type T struct{x int}
1171 | type U T
1172 |
1173 |
1174 | Here, the `Var` for field `x` belongs equally to `T`
1175 | and to `U`, and short of inspecting source positions or walking
1176 | the AST---neither of which is possible for objects loaded from compiler
1177 | export data---it is not possible to ascertain that `x` was declared as
1178 | part of `T`.
1179 | The type checker builds the exact same data structures given this input:
1180 |
1181 |
1182 | type T U
1183 | type U struct{x int}
1184 |
1185 |
1186 | A similar issue applies to the methods of named interface types.
1187 |
1188 |
1189 | ## Tuple Types
1190 |
1191 |
1192 | Like a struct, a tuple type has an ordered list of fields, and fields
1193 | may be named.
1194 |
1195 |
1196 | type Tuple struct{ ... }
1197 | func (*Tuple) Len() int
1198 | func (*Tuple) At(i int) *Var
1199 |
1200 |
1201 | Although tuples are not the type of any variable in Go, they are
1202 | the type of some expressions, such as the right-hand sides of these
1203 | assignments:
1204 |
1205 |
1206 | v, ok = m[key]
1207 | v, ok = <-ch
1208 | v, ok = x.(T)
1209 | f, err = os.Open(filename)
1210 |
1211 |
1212 | Tuples also represent the types of the parameter list and the result
1213 | list of a function, as we will see.
1214 |
1215 |
1216 |
1217 | Since empty tuples are common, the nil `*Tuple` pointer is a valid empty tuple.
1218 |
1219 |
1220 |
1221 | ## Function and Method Types
1222 |
1223 |
1224 | The types of functions and methods are represented by a `Signature`,
1225 | which has a tuple of parameter types and a tuple of result types.
1226 |
1227 |
1228 | type Signature struct{ ... }
1229 | func (*Signature) Recv() *Var
1230 | func (*Signature) Params() *Tuple
1231 | func (*Signature) Results() *Tuple
1232 | func (*Signature) Variadic() bool
1233 |
1234 |
1235 | Variadic functions such as `fmt.Println` have the `Variadic`
1236 | flag set.
1237 | The final parameter of such functions is always a slice, or in the
1238 | special case of certain calls to `append`, a string.
1239 |
1240 |
1241 |
1242 | A `Signature` for a method, whether concrete or abstract, has a
1243 | non-nil receiver parameter, `Recv`.
1244 | The type of the receiver is usually a named type or a pointer to a named type,
1245 | but it may be an unnamed struct or interface type in some cases.
1246 | Method types are rather second-class: they are only used for the
1247 | `Func` objects created by method declarations, and no Go
1248 | expression has a method type.
1249 | When printing a method type, the receiver does not appear, and the
1250 | `Identical` predicate ignores the receiver.
1251 |
1252 |
1253 |
1254 | The types of `Builtin` objects like `append` cannot be
1255 | expressed as a `Signature` since those types require parametric
1256 | polymorphism.
1257 | `Builtin` objects are thus ascribed the `Invalid` basic type.
1258 | However, the type of each _call_ to a built-in function has a specific
1259 | and expressible Go type.
1260 | These types are recorded during type checking for later use
1261 | ([TypeAndValue](#typeandvalue)).
1262 |
1263 |
1264 |
1265 | ## Named Types
1266 |
1267 |
1268 | Type declarations come in two forms.
1269 | The simplest kind, introduced in Go 1.9,
1270 | merely declares a (possibly alternative) name for an existing type.
1271 | Type names used in this way are informally called _type aliases_.
1272 | For example, this declaration lets you use the type
1273 | `Dictionary` as an alias for `map[string]string`:
1274 |
1275 | type Dictionary = map[string]string
1276 |
1277 | The declaration creates a `TypeName` object for `Dictionary`. The
1278 | object's `IsAlias` method returns true, and its `Type` method returns
1279 | a `Map` type that represents `map[string]string`.
1280 |
1281 |
1282 | The second form of type declaration, and the only kind prior to Go
1283 | 1.9, does not use an equals sign:
1284 |
1285 | type Celsius float64
1286 |
1287 | This declaration does more than just give a name to a type.
1288 | It first defines a new `Named` type
1289 | whose underlying type is `float64`; this `Named` type is different
1290 | from any other type, including `float64`. The declaration binds the
1291 | `TypeName` object to the `Named` type.
1292 |
1293 | Since Go 1.9, the Go language specification has used the term _defined
1294 | types_ instead of named types;
1295 | the essential property of a defined type is not that it has a name,
1296 | but that it is a distinct type with its own method set.
1297 | However, the type checker API predates that
1298 | change and instead calls defined types "named" types.
1299 |
1300 | type Named struct{ ... }
1301 | func (*Named) NumMethods() int
1302 | func (*Named) Method(i int) *Func
1303 | func (*Named) Obj() *TypeName
1304 | func (*Named) Underlying() Type
1305 |
1306 | The `Named` type's `Obj` method returns the `TypeName` object, which
1307 | provides the name, position, and other properties of the declaration.
1308 | Conversely, the `TypeName` object's `Type` method returns the `Named` type.
1309 |
1310 | A `Named` type may appear as the receiver type in a method declaration.
1311 | Methods are associated with the `Named` type, not the name (the
1312 | `TypeName` object); it's possible---though cryptic---to declare a
1313 | method on a `Named` type using one of its aliases.
1314 | The `NumMethods` and `Method` methods enumerate the declared
1315 | methods associated with this `Named` type (or a pointer to it),
1316 | in the order they were declared.
1317 | However, due to the subtleties of anonymous fields and the difference
1318 | between value and pointer receivers, a named type may have more or fewer
1319 | methods than this list. We'll return to this in [Method Sets](#method-sets).
1320 |
1321 |
1322 |
1323 | Every `Type` has an `Underlying` method, but for all of them
1324 | except `*Named`, it is simply the identity function.
1325 | For a named type, `Underlying` returns its underlying type, which
1326 | is always an unnamed type.
1327 | Thus `Underlying` returns `int` for both `T` and
1328 | `U` below.
1329 |
1330 |
1331 | type T int
1332 | type U T
1333 |
1334 |
1335 | Clients of the type checker often use type assertions or type switches
1336 | with a `Type` operand.
1337 | When doing so, it is often necessary to switch on the type that
1338 | _underlies_ the type of interest, and failure to do so may be a
1339 | bug.
1340 |
1341 | This is a common pattern:
1342 |
1343 |
1344 | // handle types of composite literal
1345 | switch u := t.Underlying().(type) {
1346 | case *Struct: // ...
1347 | case *Map: // ...
1348 | case *Array, *Slice: // ...
1349 | default:
1350 | panic("impossible")
1351 | }
1352 |
1353 | ## Interface Types
1354 |
1355 |
1356 | Interface types are represented by `Interface`.
1357 |
1358 |
1359 | type Interface struct{ ... }
1360 | func (*Interface) Empty() bool
1361 | func (*Interface) NumMethods() int
1362 | func (*Interface) Method(i int) *Func
1363 | func (*Interface) NumEmbeddeds() int
1364 | func (*Interface) Embedded(i int) *Named
1365 | func (*Interface) NumExplicitMethods() int
1366 | func (*Interface) ExplicitMethod(i int) *Func
1367 |
1368 |
1369 | Syntactically, an interface type has a list of explicitly declared
1370 | methods (`ExplicitMethod`), and a list of embedded named
1371 | interface types (`Embedded`), but many clients care only about
1372 | the complete set of methods, which can be enumerated via
1373 | `Method`.
1374 | All three lists are ordered by name.
1375 | Since the empty interface is an important special case, the
1376 | `Empty` predicate provides a shorthand for `NumMethods() ==
1377 | 0`.
1378 |
1379 |
1380 |
1381 | As with the fields of structs (see above), the methods of interfaces
1382 | may belong equally to more than one interface type.
1383 | The `Func` object for method `f` in the code below is shared
1384 | by `I` and `J`:
1385 |
1386 |
1387 | type I interface { f() }
1388 | type J I
1389 |
1390 |
1391 | Because the difference between interface (abstract) and
1392 | non-interface (concrete) types is so important in Go, the
1393 | `IsInterface` predicate is provided for convenience.
1394 |
1395 |
1396 | func IsInterface(Type) bool
1397 |
1398 |
1399 | The type checker provides three utility methods relating to interface
1400 | satisfaction:
1401 |
1402 |
1403 | func Implements(V Type, T *Interface) bool
1404 | func AssertableTo(V *Interface, T Type) bool
1405 | func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType bool)
1406 |
1407 |
1408 | The `Implements` predicate reports whether a type satisfies an
1409 | interface type.
1410 | `MissingMethod` is like `Implements`, but instead of
1411 | returning false, it explains why a type does not satisfy the
1412 | interface, for use in diagnostics.
1413 |
1414 |
1415 |
1416 | `AssertableTo` reports whether a type assertion `v.(T)` is legal.
1417 | If `T` is a concrete type that doesn't have all the methods of
1418 | interface `v`, then the type assertion is not legal, as in this example:
1419 |
1420 |
1421 | // error: io.Writer is not assertible to int
1422 | func f(w io.Writer) int { return w.(int) }
1423 |
1424 |
1425 |
1426 | ## TypeAndValue
1427 |
1428 |
1429 | The type checker records the type of each expression in another field
1430 | of the `Info` struct, namely `Types`:
1431 |
1432 |
1433 | type Info struct {
1434 | ...
1435 | Types map[ast.Expr]TypeAndValue
1436 | }
1437 |
1438 |
1439 | No entries are recorded for identifiers since the `Defs` and
1440 | `Uses` maps provide more information about them.
1441 | Also, no entries are recorded for pseudo-expressions like
1442 | `*ast.KeyValuePair` or `*ast.Ellipsis`.
1443 |
1444 |
1445 |
1446 | The value of the `Types` map is a `TypeAndValue`, which
1447 | (unsurprisingly) holds the type and value of the expression, and in
1448 | addition, its _mode_.
1449 | The mode is opaque, but has predicates to answer questions such as:
1450 | Does this expression denote a value or a type? Does this value have an
1451 | address? Does this expression appear on the left-hand side of an
1452 | assignment? Does this expression appear in a context that expects two
1453 | results?
1454 | The comments in the code below give examples of expressions that
1455 | satisfy each predicate.
1456 |
1457 |
1458 | type TypeAndValue struct {
1459 | Type Type
1460 | Value constant.Value // for constant expressions only
1461 | ...
1462 | }
1463 |
1464 | func (TypeAndValue) IsVoid() bool // e.g. "main()"
1465 | func (TypeAndValue) IsType() bool // e.g. "*os.File"
1466 | func (TypeAndValue) IsBuiltin() bool // e.g. "len(x)"
1467 | func (TypeAndValue) IsValue() bool // e.g. "*os.Stdout"
1468 | func (TypeAndValue) IsNil() bool // e.g. "nil"
1469 | func (TypeAndValue) Addressable() bool // e.g. "a[i]" but not "f()", "m[key]"
1470 | func (TypeAndValue) Assignable() bool // e.g. "a[i]", "m[key]"
1471 | func (TypeAndValue) HasOk() bool // e.g. "<-ch", "m[key]"
1472 |
1473 |
1474 | The statement below inspects every expression within the AST of a single
1475 | type-checked file and prints its type, value, and mode:
1476 |
1477 |
1478 | // go get golang.org/x/example/gotypes/typeandvalue
1479 |
1480 | ```
1481 | // f is a parsed, type-checked *ast.File.
1482 | ast.Inspect(f, func(n ast.Node) bool {
1483 | if expr, ok := n.(ast.Expr); ok {
1484 | if tv, ok := info.Types[expr]; ok {
1485 | fmt.Printf("%-24s\tmode: %s\n", nodeString(expr), mode(tv))
1486 | fmt.Printf("\t\t\t\ttype: %v\n", tv.Type)
1487 | if tv.Value != nil {
1488 | fmt.Printf("\t\t\t\tvalue: %v\n", tv.Value)
1489 | }
1490 | }
1491 | }
1492 | return true
1493 | })
1494 | ```
1495 |
1496 |
1497 | It makes use of these two helper functions, which are not shown:
1498 |
1499 |
1500 | // nodeString formats a syntax tree in the style of gofmt.
1501 | func nodeString(n ast.Node) string
1502 |
1503 | // mode returns a string describing the mode of an expression.
1504 | func mode(tv types.TypeAndValue) string
1505 |
1506 |
1507 | Given this input:
1508 |
1509 |
1510 | ```
1511 | const input = `
1512 | package main
1513 |
1514 | var m = make(map[string]int)
1515 |
1516 | func main() {
1517 | v, ok := m["hello, " + "world"]
1518 | print(rune(v), ok)
1519 | }
1520 | `
1521 | ```
1522 |
1523 |
1524 | the program prints:
1525 |
1526 |
1527 | ```
1528 | $ go build golang.org/x/example/gotypes/typeandvalue
1529 | $ ./typeandvalue
1530 | make(map[string]int) mode: value
1531 | type: map[string]int
1532 | make mode: builtin
1533 | type: func(map[string]int) map[string]int
1534 | map[string]int mode: type
1535 | type: map[string]int
1536 | string mode: type
1537 | type: string
1538 | int mode: type
1539 | type: int
1540 | m["hello, "+"world"] mode: value,assignable,ok
1541 | type: (int, bool)
1542 | m mode: value,addressable,assignable
1543 | type: map[string]int
1544 | "hello, " + "world" mode: value
1545 | type: string
1546 | value: "hello, world"
1547 | "hello, " mode: value
1548 | type: untyped string
1549 | value: "hello, "
1550 | "world" mode: value
1551 | type: untyped string
1552 | value: "world"
1553 | print(rune(v), ok) mode: void
1554 | type: ()
1555 | print mode: builtin
1556 | type: func(rune, bool)
1557 | rune(v) mode: value
1558 | type: rune
1559 | rune mode: type
1560 | type: rune
1561 | ...more not shown...
1562 | ```
1563 |
1564 |
1565 | Notice that the identifiers for the built-ins `make` and
1566 | `print` have types that are specific to the particular calls in
1567 | which they appear.
1568 | Also notice `m["hello"]` has a 2-tuple type `(int, bool)`
1569 | and that it is assignable, but unlike the variable `m`, it is not
1570 | addressable.
1571 |
1572 |
1573 |
1574 | Download the example and vary the inputs and see what the program prints.
1575 |
1576 |
1577 |
1578 | Here's another example, adapted from the `govet` static checking tool.
1579 | It checks for accidental uses of a method value `x.f` when a
1580 | call `x.f()` was intended;
1581 | comparing a method `x.f` against nil is a common mistake.
1582 |
1583 |
1584 | // go get golang.org/x/example/gotypes/nilfunc
1585 |
1586 | ```
1587 | // CheckNilFuncComparison reports unintended comparisons
1588 | // of functions against nil, e.g., "if x.Method == nil {".
1589 | func CheckNilFuncComparison(info *types.Info, n ast.Node) {
1590 | e, ok := n.(*ast.BinaryExpr)
1591 | if !ok {
1592 | return // not a binary operation
1593 | }
1594 | if e.Op != token.EQL && e.Op != token.NEQ {
1595 | return // not a comparison
1596 | }
1597 |
1598 | // If this is a comparison against nil, find the other operand.
1599 | var other ast.Expr
1600 | if info.Types[e.X].IsNil() {
1601 | other = e.Y
1602 | } else if info.Types[e.Y].IsNil() {
1603 | other = e.X
1604 | } else {
1605 | return // not a comparison against nil
1606 | }
1607 |
1608 | // Find the object.
1609 | var obj types.Object
1610 | switch v := other.(type) {
1611 | case *ast.Ident:
1612 | obj = info.Uses[v]
1613 | case *ast.SelectorExpr:
1614 | obj = info.Uses[v.Sel]
1615 | default:
1616 | return // not an identifier or selection
1617 | }
1618 |
1619 | if _, ok := obj.(*types.Func); !ok {
1620 | return // not a function or method
1621 | }
1622 |
1623 | fmt.Printf("%s: comparison of function %v %v nil is always %v\n",
1624 | fset.Position(e.Pos()), obj.Name(), e.Op, e.Op == token.NEQ)
1625 | }
1626 | ```
1627 |
1628 |
1629 | Given this input,
1630 |
1631 |
1632 | ```
1633 | const input = `package main
1634 |
1635 | import "bytes"
1636 |
1637 | func main() {
1638 | var buf bytes.Buffer
1639 | if buf.Bytes == nil && bytes.Repeat != nil && main == nil {
1640 | // ...
1641 | }
1642 | }
1643 | `
1644 | ```
1645 |
1646 |
1647 | the program reports these errors:
1648 |
1649 |
1650 | ```
1651 | $ go build golang.org/x/example/gotypes/nilfunc
1652 | $ ./nilfunc
1653 | input.go:7:5: comparison of function Bytes == nil is always false
1654 | input.go:7:25: comparison of function Repeat != nil is always true
1655 | input.go:7:48: comparison of function main == nil is always false
1656 | ```
1657 |
1658 | # Selections
1659 |
1660 |
1661 | A _selection_ is an expression _`expr`_`.f` in which
1662 | `f` denotes either a struct field or a method.
1663 | A selection is resolved not by looking for a name in the lexical
1664 | environment, but by looking within a _type_.
1665 | The type checker ascertains the meaning of each selection in the
1666 | package---a surprisingly tricky business---and records it in the
1667 | `Selections` mapping of the `Info` struct, whose values are
1668 | of type `Selection`:
1669 |
1670 |
1671 | type Selection struct{ ... }
1672 | func (s *Selection) Kind() SelectionKind // = FieldVal | MethodVal | MethodExpr
1673 | func (s *Selection) Recv() Type
1674 | func (s *Selection) Obj() Object
1675 | func (s *Selection) Type() Type
1676 | func (s *Selection) Index() []int
1677 | func (s *Selection) Indirect() bool
1678 |
1679 |
1680 | The `Kind` method discriminates between the three (legal) kinds
1681 | of selections, as indicated by the comments below.
1682 |
1683 |
1684 | type T struct{Field int}
1685 | func (T) Method() {}
1686 | var v T
1687 |
1688 | // Kind Type
1689 | var _ = v.Field // FieldVal int
1690 | var _ = v.Method // MethodVal func()
1691 | var _ = T.Method // MethodExpr func(T)
1692 |
1693 |
1694 | Because of embedding, a selection may denote more than one field or
1695 | method, in which case it is ambiguous, and no `Selection` is
1696 | recorded for it.
1697 |
1698 |
1699 |
1700 | The `Obj` method returns the `Object` for the selected field
1701 | (`*Var`) or method (`*Func`).
1702 | Due to embedding, the object may belong to a different type than that
1703 | of the receiver expression _`expr`_.
1704 | The `Type` method returns the type of the selection. For a field
1705 | selection, this is the type of the field, but for method selections,
1706 | the result is a function type that is not the same as the type of the
1707 | method.
1708 | For a `MethodVal`, the receiver parameter is dropped, and
1709 | for a `MethodExpr`, the receiver parameter becomes a regular
1710 | parameter, as shown in the example above.
1711 |
1712 |
1713 |
1714 | The `Index` and `Indirect` methods report information about
1715 | implicit operations occurring during the selection that a compiler
1716 | would need to know about.
1717 | Because of embedding, a selection _`expr`_`.f` may be
1718 | shorthand for a sequence containing several implicit field selections,
1719 | _`expr`_`.d.e.f`, and `Index` reports the complete
1720 | sequence.
1721 | And because of automatic pointer dereferencing during struct field
1722 | accesses and method calls, a selection may imply one or more indirect
1723 | loads from memory; `Indirect` reports whether this occurs.
1724 |
1725 |
1726 |
1727 | Clients of the type checker can call `LookupFieldOrMethod` to
1728 | look up a name within a type, as if by a selection.
1729 | This function has an intimidating signature, but conceptually it
1730 | accepts just a `Type` and a name, and returns a `Selection`:
1731 |
1732 |
1733 | func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) \
1734 | (obj Object, index []int, indirect bool)
1735 |
1736 |
1737 | The result is not actually a `Selection`, but it contains the
1738 | three main components of one: `Obj`, `Index`,
1739 | and `Indirect`.
1740 |
1741 |
1742 |
1743 | The `addressable` flag should be set if the receiver is a
1744 | _variable_ of type `T`, since in a method selection on a
1745 | variable, an implicit address-of operation (`&`) may occur.
1746 | The flag indicates whether the methods of type `*T` should be
1747 | considered during the lookup.
1748 | (You may wonder why this parameter is necessary. Couldn't clients
1749 | instead call `LookupFieldOrMethod` on the pointer type `*T`
1750 | if the receiver is a `T` variable? The answer is that if
1751 | `T` is an interface type, the type `*T` has no methods at
1752 | all.)
1753 |
1754 |
1755 |
1756 | The final two parameters of `LookupFieldOrMethod` are `(pkg
1757 | *Package, name string)`.
1758 | Together they specify the name of the field or method to look up.
1759 | This brings us to `Id`s.
1760 |
1761 |
1762 |
1763 | # Ids
1764 |
1765 |
1766 | `LookupFieldOrMethod`'s need for a `Package` parameter
1767 | is a subtle consequence of the
1768 | [_Uniqueness of identifiers_](https://golang.org/ref/spec#Uniqueness_of_identifiers)
1769 | section in the Go spec: "Two
1770 | identifiers are different if they are spelled differently, or if they
1771 | appear in different packages and are not exported."
1772 | In practical terms, this means that a type may have two methods
1773 | (or two fields, or one of each) both named `f` so long as those
1774 | methods are defined in different packages, as in this example:
1775 |
1776 |
1777 | package a
1778 | type A int
1779 | func (A) f()
1780 |
1781 | package b
1782 | type B int
1783 | func (B) f()
1784 |
1785 | package c
1786 | import ( "a"; "b" )
1787 | type C struct{a.A; b.B} // C has two methods called f
1788 |
1789 |
1790 | The type `c.C` has two methods named `f`, but there is
1791 | no ambiguity because the two `f`s are distinct
1792 | identifiers---think of them as `fᵃ` and `fᵇ`.
1793 | For an exported method, this situation _would_ be ambiguous
1794 | because there is no distinction between `Fᵃ` and `Fᵇ`; there
1795 | is only `F`.
1796 |
1797 |
1798 |
1799 | Despite having two methods called `f`, neither of them can be
1800 | called from within package `c` because `c` has no way to
1801 | identify them.
1802 | Within `c`, `f` is the identifier `fᶜ`, and
1803 | type `C` has no method of that name.
1804 | But if we pass an instance of `C` to code in package `a`
1805 | and call its `f` method via an interface, `fᵃ` is called.
1806 |
1807 |
1808 |
1809 | The practical consequence for tool builders is that any time you need
1810 | to look up a field or method by name, or construct a map of fields and/or
1811 | methods keyed by name, it is not sufficient to use the object's name
1812 | as a key.
1813 | Instead, you must call the `Object.Id` method, which returns
1814 | a string that incorporates the object name, and for unexported
1815 | objects, the package path too.
1816 | There is also a standalone function `Id` that combines a name and
1817 | the package path in the same way:
1818 |
1819 |
1820 | func Id(pkg *Package, name string) string
1821 |
1822 |
1823 | This distinction applies to selections _`expr`_`.f`, but not
1824 | to lexical references `x` because for unexported identifiers,
1825 | declarations and references always appear in the same package.
1826 |
1827 |
1828 |
1829 | Fun fact: the `reflect.StructField` type records both the
1830 | `Name` and the `PkgPath` strings for the same reason.
1831 | The `FieldByName` methods of `reflect.Value` and
1832 | `reflect.Type` match field names without regard to the package.
1833 | If there is more than one match, they return an invalid value.
1834 |
1835 |
1836 |
1837 |
1838 | # Method Sets
1839 |
1840 |
1841 | The _method set_ of a type is the set of methods that can be
1842 | called on any value of that type.
1843 | (A variable of type `T` has access to all the methods of type
1844 | `*T` as well, due to the implicit address-of operation during
1845 | method calls, but those extra methods are not part of the method set
1846 | of `T`.)
1847 |
1848 |
1849 |
1850 | Clients can request the method set of a type `T` by calling
1851 | `NewMethodSet(T)`:
1852 |
1853 |
1854 | type MethodSet struct{ ... }
1855 | func NewMethodSet(T Type) *MethodSet
1856 | func (s *MethodSet) Len() int
1857 | func (s *MethodSet) At(i int) *Selection
1858 | func (s *MethodSet) Lookup(pkg *Package, name string) *Selection
1859 |
1860 |
1861 | The `Len` and `At` methods access a list of
1862 | `Selections`, all of kind `MethodVal`, ordered by `Id`.
1863 | The `Lookup` function allows lookup of a single method by
1864 | name (and package path, as explained in the previous section).
1865 |
1866 |
1867 |
1868 | `NewMethodSet` can be expensive, so for applications that compute
1869 | method sets repeatedly, `golang.org/x/tools/go/types/typeutil`
1870 | provides a `MethodSetCache` type that records previous results.
1871 | If you only need a single method, don't construct the
1872 | `MethodSet` at all; it's cheaper to use
1873 | `LookupFieldOrMethod`.
1874 |
1875 |
1876 |
1877 | The next program generates a boilerplate
1878 | declaration of a new concrete type that satisfies an existing
1879 | interface.
1880 | Here's an example:
1881 |
1882 |
1883 | ```
1884 | $ ./skeleton io ReadWriteCloser buffer
1885 | // *buffer implements io.ReadWriteCloser.
1886 | type buffer struct{}
1887 | func (b *buffer) Close() error {
1888 | panic("unimplemented")
1889 | }
1890 | func (b *buffer) Read(p []byte) (n int, err error) {
1891 | panic("unimplemented")
1892 | }
1893 | func (b *buffer) Write(p []byte) (n int, err error) {
1894 | panic("unimplemented")
1895 | }
1896 | ```
1897 |
1898 |
1899 | The three arguments are the package and the name of the existing
1900 | interface type, and the name of the new concrete type.
1901 | The `main` function (not shown) loads the specified package and
1902 | calls `PrintSkeleton` with the remaining two arguments:
1903 |
1904 |
1905 | // go get golang.org/x/example/gotypes/skeleton
1906 |
1907 | ```
1908 | func PrintSkeleton(pkg *types.Package, ifacename, concname string) error {
1909 | obj := pkg.Scope().Lookup(ifacename)
1910 | if obj == nil {
1911 | return fmt.Errorf("%s.%s not found", pkg.Path(), ifacename)
1912 | }
1913 | if _, ok := obj.(*types.TypeName); !ok {
1914 | return fmt.Errorf("%v is not a named type", obj)
1915 | }
1916 | iface, ok := obj.Type().Underlying().(*types.Interface)
1917 | if !ok {
1918 | return fmt.Errorf("type %v is a %T, not an interface",
1919 | obj, obj.Type().Underlying())
1920 | }
1921 | // Use first letter of type name as receiver parameter.
1922 | if !isValidIdentifier(concname) {
1923 | return fmt.Errorf("invalid concrete type name: %q", concname)
1924 | }
1925 | r, _ := utf8.DecodeRuneInString(concname)
1926 |
1927 | fmt.Printf("// *%s implements %s.%s.\n", concname, pkg.Path(), ifacename)
1928 | fmt.Printf("type %s struct{}\n", concname)
1929 | mset := types.NewMethodSet(iface)
1930 | for i := 0; i < mset.Len(); i++ {
1931 | meth := mset.At(i).Obj()
1932 | sig := types.TypeString(meth.Type(), (*types.Package).Name)
1933 | fmt.Printf("func (%c *%s) %s%s {\n\tpanic(\"unimplemented\")\n}\n",
1934 | r, concname, meth.Name(),
1935 | strings.TrimPrefix(sig, "func"))
1936 | }
1937 | return nil
1938 | }
1939 | ```
1940 |
1941 |
1942 | First, `PrintSkeleton` locates the package-level named interface
1943 | type, handling various error cases.
1944 | Then it chooses the name for the receiver of the new methods: the
1945 | first letter of the concrete type.
1946 | Finally, it iterates over the method set of the interface, printing
1947 | the corresponding concrete method declarations.
1948 |
1949 |
1950 |
1951 | There's a subtlety in the declaration of `sig`, which is the
1952 | string form of the method signature.
1953 | We could have obtained this string from `meth.Type().String()`,
1954 | but this would cause any named types within it to be formatted with
1955 | the complete package path, for instance
1956 | `net/http.ResponseWriter`, which is informative in diagnostics
1957 | but not legal Go syntax.
1958 | The `TypeString` function (explained in [Formatting Values](#formatting-values)) allows the
1959 | caller to control how packages are printed.
1960 | Passing `(*types.Package).Name` causes only the package name
1961 | `http` to be printed, not the complete path.
1962 | Here's another example that illustrates it:
1963 |
1964 |
1965 | ```
1966 | $ ./skeleton net/http Handler myHandler
1967 | // *myHandler implements net/http.Handler.
1968 | type myHandler struct{}
1969 | func (m *myHandler) ServeHTTP(http.ResponseWriter, *http.Request) {
1970 | panic("unimplemented")
1971 | }
1972 | ```
1973 |
1974 |
1975 | The following program inspects all pairs of package-level named types
1976 | in `pkg`, and reports the types that satisfy each interface type.
1977 |
1978 |
1979 | // go get golang.org/x/example/gotypes/implements
1980 |
1981 | ```
1982 | // Find all named types at package level.
1983 | var allNamed []*types.Named
1984 | for _, name := range pkg.Scope().Names() {
1985 | if obj, ok := pkg.Scope().Lookup(name).(*types.TypeName); ok {
1986 | allNamed = append(allNamed, obj.Type().(*types.Named))
1987 | }
1988 | }
1989 |
1990 | // Test assignability of all distinct pairs of
1991 | // named types (T, U) where U is an interface.
1992 | for _, T := range allNamed {
1993 | for _, U := range allNamed {
1994 | if T == U || !types.IsInterface(U) {
1995 | continue
1996 | }
1997 | if types.AssignableTo(T, U) {
1998 | fmt.Printf("%s satisfies %s\n", T, U)
1999 | } else if !types.IsInterface(T) &&
2000 | types.AssignableTo(types.NewPointer(T), U) {
2001 | fmt.Printf("%s satisfies %s\n", types.NewPointer(T), U)
2002 | }
2003 | }
2004 | }
2005 | ```
2006 |
2007 |
2008 | Given this input,
2009 |
2010 |
2011 | // go get golang.org/x/example/gotypes/implements
2012 |
2013 | ```
2014 | const input = `package main
2015 |
2016 | type A struct{}
2017 | func (*A) f()
2018 |
2019 | type B int
2020 | func (B) f()
2021 | func (*B) g()
2022 |
2023 | type I interface { f() }
2024 | type J interface { g() }
2025 | `
2026 | ```
2027 |
2028 |
2029 | the program prints:
2030 |
2031 |
2032 | ```
2033 | $ go build golang.org/x/example/gotypes/implements
2034 | $ ./implements
2035 | *hello.A satisfies hello.I
2036 | hello.B satisfies hello.I
2037 | *hello.B satisfies hello.J
2038 | ```
2039 |
2040 |
2041 | Notice that the method set of `B` does not include `g`, but
2042 | the method set of `*B` does.
2043 | That's why we needed the second assignability check, using the pointer
2044 | type `types.NewPointer(T)`.
2045 |
2046 |
2047 |
2048 | # Constants
2049 |
2050 |
2051 | A constant expression is one whose value is guaranteed to be computed at
2052 | compile time.
2053 | Constant expressions may appear in types, specifically as the length
2054 | of an array type such as `[16]byte`, so one of the jobs of the
2055 | type checker is to compute the value of each constant expression.
2056 |
2057 |
2058 |
2059 | As we saw in the `typeandvalue` example, the type checker records
2060 | the value of each constant expression like `"Hello, " + "world"`,
2061 | storing it in the `Value` field of the `TypeAndValue` struct.
2062 | Constants are represented using the `Value` interface from the
2063 | `go/constant` package.
2064 |
2065 |
2066 | package constant // go/constant
2067 |
2068 | type Value interface {
2069 | Kind() Kind
2070 | }
2071 |
2072 | type Kind int // one of Unknown, Bool, String, Int, Float, Complex
2073 |
2074 |
2075 | The interface has only one method, for discriminating the various
2076 | kinds of constants, but the package provides many functions for
2077 | inspecting a value of a known kind,
2078 |
2079 |
2080 | // Accessors
2081 | func BoolVal(x Value) bool
2082 | func Float32Val(x Value) (float32, bool)
2083 | func Float64Val(x Value) (float64, bool)
2084 | func Int64Val(x Value) (int64, bool)
2085 | func StringVal(x Value) string
2086 | func Uint64Val(x Value) (uint64, bool)
2087 | func Bytes(x Value) []byte
2088 | func BitLen(x Value) int
2089 | func Sign(x Value) int
2090 |
2091 |
2092 | for performing arithmetic on values,
2093 |
2094 |
2095 | // Operations
2096 | func Compare(x Value, op token.Token, y Value) bool
2097 | func UnaryOp(op token.Token, y Value, prec uint) Value
2098 | func BinaryOp(x Value, op token.Token, y Value) Value
2099 | func Shift(x Value, op token.Token, s uint) Value
2100 | func Denom(x Value) Value
2101 | func Num(x Value) Value
2102 | func Real(x Value) Value
2103 | func Imag(x Value) Value
2104 |
2105 |
2106 | and for constructing new values:
2107 |
2108 |
2109 | // Constructors
2110 | func MakeBool(b bool) Value
2111 | func MakeFloat64(x float64) Value
2112 | func MakeFromBytes(bytes []byte) Value
2113 | func MakeFromLiteral(lit string, tok token.Token, prec uint) Value
2114 | func MakeImag(x Value) Value
2115 | func MakeInt64(x int64) Value
2116 | func MakeString(s string) Value
2117 | func MakeUint64(x uint64) Value
2118 | func MakeUnknown() Value
2119 |
2120 |
2121 | All numeric `Value`s, whether integer or floating-point, signed or
2122 | unsigned, or real or complex, are represented more precisely than
2123 | ordinary Go types like `int64` and `float64`.
2124 | Internally, the `go/constant` package uses multi-precision data types
2125 | like `Int`, `Rat`, and `Float` from the `math/big` package so that
2126 | `Values` and their arithmetic operations are accurate to at least 256
2127 | bits, as required by the Go specification.
2128 |
2129 |
2130 |
2131 |
2132 |
2133 | # Size and Alignment
2134 |
2135 |
2136 | Because the calls `unsafe.Sizeof(v)`, `unsafe.Alignof(v)`,
2137 | and `unsafe.Offsetof(v.f)` are all constant expressions, the type
2138 | checker must be able to compute the memory layout of any value
2139 | `v`.
2140 |
2141 |
2142 |
2143 | By default, the type checker uses the same layout algorithm as the Go
2144 | 1.5 `gc` compiler targeting `amd64`.
2145 | Clients can configure the type checker to use a different algorithm by
2146 | providing an instance of the `types.Sizes` interface in the
2147 | `types.Config` struct:
2148 |
2149 |
2150 | package types
2151 |
2152 | type Sizes interface {
2153 | Alignof(T Type) int64
2154 | Offsetsof(fields []*Var) []int64
2155 | Sizeof(T Type) int64
2156 | }
2157 |
2158 |
2159 |
2160 | For common changes, like reducing the word size to 32 bits, clients
2161 | can use an instance of `StdSizes`:
2162 |
2163 |
2164 | type StdSizes struct {
2165 | WordSize int64
2166 | MaxAlign int64
2167 | }
2168 |
2169 |
2170 | This type has two basic size and alignment parameters from which it
2171 | derives all the other values using common assumptions.
2172 | For example, pointers, functions, maps, and channels fit in one word,
2173 | strings and interfaces require two words, and slices need three.
2174 | The default behaviour is equivalent to `StdSizes{8, 8}`.
2175 | For more esoteric layout changes, you'll need to write a new
2176 | implementation of the `Sizes` interface.
2177 |
2178 |
2179 |
2180 | The `hugeparam` program below prints all function parameters and
2181 | results whose size exceeds a threshold.
2182 | By default, the threshold is 48 bytes, but you can set it via the
2183 | `-bytes` command-line flag.
2184 | Such a tool could help identify inefficient parameter passing in your
2185 | programs.
2186 |
2187 |
2188 | // go get golang.org/x/example/gotypes/hugeparam
2189 |
2190 | ```
2191 | var bytesFlag = flag.Int("bytes", 48, "maximum parameter size in bytes")
2192 |
2193 | var sizeof = (&types.StdSizes{8, 8}).Sizeof // the sizeof function
2194 |
2195 | func PrintHugeParams(fset *token.FileSet, info *types.Info, files []*ast.File) {
2196 | checkTuple := func(descr string, tuple *types.Tuple) {
2197 | for i := 0; i < tuple.Len(); i++ {
2198 | v := tuple.At(i)
2199 | if sz := sizeof(v.Type()); sz > int64(*bytesFlag) {
2200 | fmt.Printf("%s: %q %s: %s = %d bytes\n",
2201 | fset.Position(v.Pos()),
2202 | v.Name(), descr, v.Type(), sz)
2203 | }
2204 | }
2205 | }
2206 | checkSig := func(sig *types.Signature) {
2207 | checkTuple("parameter", sig.Params())
2208 | checkTuple("result", sig.Results())
2209 | }
2210 | for _, file := range files {
2211 | ast.Inspect(file, func(n ast.Node) bool {
2212 | switch n := n.(type) {
2213 | case *ast.FuncDecl:
2214 | checkSig(info.Defs[n.Name].Type().(*types.Signature))
2215 | case *ast.FuncLit:
2216 | checkSig(info.Types[n.Type].Type.(*types.Signature))
2217 | }
2218 | return true
2219 | })
2220 | }
2221 | }
2222 | ```
2223 |
2224 |
2225 | As before, `Inspect` applies a function to every node in the AST.
2226 | The function cares about two kinds of nodes: declarations of named
2227 | functions and methods (`*ast.FuncDecl`) and function literals
2228 | (`*ast.FuncLit`).
2229 | Observe the two cases' different logic to obtain the type of each
2230 | function.
2231 |
2232 |
2233 |
2234 | Here's a typical invocation on the standard `encoding/xml` package.
2235 | It reports a number of places where the 7-word
2236 | [`StartElement` type](https://pkg.go.dev/encoding/xml#StartElement)
2237 | is copied.
2238 |
2239 |
2240 | ```
2241 | % ./hugeparam encoding/xml
2242 | /go/src/encoding/xml/marshal.go:167:50: "start" parameter: encoding/xml.StartElement = 56 bytes
2243 | /go/src/encoding/xml/marshal.go:734:97: "" result: encoding/xml.StartElement = 56 bytes
2244 | /go/src/encoding/xml/marshal.go:761:51: "start" parameter: encoding/xml.StartElement = 56 bytes
2245 | /go/src/encoding/xml/marshal.go:781:68: "start" parameter: encoding/xml.StartElement = 56 bytes
2246 | /go/src/encoding/xml/xml.go:72:30: "" result: encoding/xml.StartElement = 56 bytes
2247 | ```
2248 |
2249 | # Imports
2250 |
2251 |
2252 | The type checker's `Check` function processes a slice of parsed
2253 | files (`[]*ast.File`) that make up one package.
2254 | When the type checker encounters an import declaration, it needs the
2255 | type information for the objects in the imported package.
2256 | It gets it by calling the `Import` method of the `Importer`
2257 | interface shown below, an instance of which must be provided by the
2258 | `Config`.
2259 | This separation of concerns relieves the type checker from having to
2260 | know any of the details of Go workspace organization, `GOPATH`,
2261 | compiler file formats, and so on.
2262 |
2263 |
2264 | type Importer interface {
2265 | Import(path string) (*Package, error)
2266 | }
2267 |
2268 |
2269 | Most of our examples used the simplest `Importer` implementation,
2270 | `importer.Default()`, provided by the `go/importer` package.
2271 | This importer looks in `$GOROOT` and `$GOPATH` for `.a`
2272 | files written by the compiler (`gc` or `gccgo`)
2273 | that was used to build the program.
2274 | In addition to object code, these files contain _export data_,
2275 | that is, a description of all the objects declared by the package, and
2276 | also of any objects from other packages that were referred to indirectly.
2277 | Because export data includes information about dependencies, the type
2278 | checker need load at most one file per import, instead of one per
2279 | transitive dependency.
2280 |
2281 |
2282 |
2283 | Compiler export data is compact and efficient to locate, load, and
2284 | parse, but it has several shortcomings.
2285 | First, it does not contain position information for imported
2286 | objects, reducing the quality of certain diagnostic messages.
2287 | Second, it does not contain complete syntax trees nor semantic information
2288 | about the contents of function bodies, so it is not suitable for
2289 | interprocedural analyses.
2290 | Third, compiler object data may be stale. Nothing detects or ensures
2291 | that the object files are more recent than the source files from which
2292 | they were derived.
2293 | Generally, object data for standard packages is likely to be
2294 | up-to-date, but for user packages, it depends on how recently the user
2295 | ran a `go install` or `go build -i` command.
2296 |
2297 |
2298 |
2299 | The [`golang.org/tools/x/go/loader` package](https://pkg.go.dev/golang.org/x/tools/go/loader)
2300 | provides an alternative `Importer` that addresses
2301 | some of these problems.
2302 | It loads a complete program from source, performing
2303 | [`cgo`](https://golang.org/cmd/cgo/cgo) preprocessing if
2304 | necessary, followed by parsing and type-checking.
2305 | It loads independent packages in parallel to hide I/O latency, and
2306 | detects and reports import cycles.
2307 | For each package, it provides the `types.Package` containing the
2308 | package's lexical environment, the list of `ast.File` syntax
2309 | trees for each file in the package, the `types.Info` containing
2310 | type information for each syntax node, and a list of type errors
2311 | associated with that package.
2312 | (Please be aware that the `go/loader` package's API is likely to
2313 | change before it finally stabilizes.)
2314 |
2315 |
2316 |
2317 | The `doc` program below demonstrates a simple use of the loader.
2318 | It is a rudimentary implementation of `go doc` that prints the type,
2319 | methods, and documentation of the package-level object specified on
2320 | the command line.
2321 | Here's an example:
2322 |
2323 |
2324 | ```
2325 | $ ./doc net/http File
2326 | type net/http.File interface{Readdir(count int) ([]os.FileInfo, error); Seek(offset int64, whence int) (int64, error); Stat() (os.FileInfo, error); io.Closer; io.Reader}
2327 | /go/src/io/io.go:92:2: method (net/http.File) Close() error
2328 | /go/src/io/io.go:71:2: method (net/http.File) Read(p []byte) (n int, err error)
2329 | /go/src/net/http/fs.go:65:2: method (net/http.File) Readdir(count int) ([]os.FileInfo, error)
2330 | /go/src/net/http/fs.go:66:2: method (net/http.File) Seek(offset int64, whence int) (int64, error)
2331 | /go/src/net/http/fs.go:67:2: method (net/http.File) Stat() (os.FileInfo, error)
2332 |
2333 | A File is returned by a FileSystem's Open method and can be
2334 | served by the FileServer implementation.
2335 |
2336 | The methods should behave the same as those on an *os.File.
2337 | ```
2338 |
2339 |
2340 | Observe that it prints the correct location of each method
2341 | declaration, even though, due to embedding, some of
2342 | `http.File`'s methods were declared in another package.
2343 | Here's the first part of the program, showing how to load an entire
2344 | program starting from the single package, `pkgpath`:
2345 |
2346 |
2347 | // go get golang.org/x/example/gotypes/doc
2348 |
2349 | ```
2350 | pkgpath, name := os.Args[1], os.Args[2]
2351 |
2352 | // The loader loads a complete Go program from source code.
2353 | conf := loader.Config{ParserMode: parser.ParseComments}
2354 | conf.Import(pkgpath)
2355 | lprog, err := conf.Load()
2356 | if err != nil {
2357 | log.Fatal(err) // load error
2358 | }
2359 |
2360 | // Find the package and package-level object.
2361 | pkg := lprog.Package(pkgpath).Pkg
2362 | obj := pkg.Scope().Lookup(name)
2363 | if obj == nil {
2364 | log.Fatalf("%s.%s not found", pkg.Path(), name)
2365 | }
2366 | ```
2367 |
2368 |
2369 | Notice that we instructed the parser to retain comments during parsing.
2370 | The rest of the program prints the output:
2371 |
2372 |
2373 | // go get golang.org/x/example/gotypes/doc
2374 |
2375 | ```
2376 | // Print the object and its methods (incl. location of definition).
2377 | fmt.Println(obj)
2378 | for _, sel := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {
2379 | fmt.Printf("%s: %s\n", lprog.Fset.Position(sel.Obj().Pos()), sel)
2380 | }
2381 |
2382 | // Find the path from the root of the AST to the object's position.
2383 | // Walk up to the enclosing ast.Decl for the doc comment.
2384 | _, path, _ := lprog.PathEnclosingInterval(obj.Pos(), obj.Pos())
2385 | for _, n := range path {
2386 | switch n := n.(type) {
2387 | case *ast.GenDecl:
2388 | fmt.Println("\n", n.Doc.Text())
2389 | return
2390 | case *ast.FuncDecl:
2391 | fmt.Println("\n", n.Doc.Text())
2392 | return
2393 | }
2394 | }
2395 | ```
2396 |
2397 |
2398 | We used `IntuitiveMethodSet` to compute the method set, instead
2399 | of `NewMethodSet`.
2400 | The result of this convenience function, which is intended for use in
2401 | user interfaces, includes methods of `*T` as well as those of
2402 | `T`, since that matches most users' intuition about the method
2403 | set of a type.
2404 | (Our example, `http.File`, didn't illustrate the difference, but try
2405 | running it on a type with both value and pointer methods.)
2406 |
2407 |
2408 |
2409 | Also notice `PathEnclosingInterval`, which finds the set of AST
2410 | nodes that enclose a particular point, in this case, the object's
2411 | declaring identifier.
2412 | By walking up with path, we find the enclosing declaration, to which
2413 | the documentation is attached.
2414 |
2415 |
2416 |
2417 | # Formatting support
2418 |
2419 |
2420 | All types that satisfy `Type` or `Object` define a
2421 | `String` method that formats the type or object in a readable
2422 | notation. `Selection` also provides a `String` method.
2423 | All package-level objects within these data structures are
2424 | printed with the complete package path, as in these examples:
2425 |
2426 |
2427 | []encoding/json.Marshaler // a *Slice type
2428 | encoding/json.Marshal // a *Func object
2429 | (*encoding/json.Encoder).Encode // a *Func object (method)
2430 | func (enc *encoding/json.Encoder) Encode(v interface{}) error // a method *Signature
2431 | func NewEncoder(w io.Writer) *encoding/json.Encoder // a function *Signature
2432 |
2433 |
2434 | This notation is unambiguous, but it is not legal Go syntax.
2435 | Also, package paths may be long, and the same package path may appear
2436 | many times in a single string, for instance, when formatting a
2437 | function of several parameters.
2438 | Because these strings often form part of a tool's user interface---as
2439 | with the diagnostic messages of `hugeparam` or the code generated
2440 | by `skeleton`---many clients want more control over the
2441 | formatting of package names.
2442 |
2443 |
2444 |
2445 | The `go/types` package provides these alternatives to the
2446 | `String` methods:
2447 |
2448 |
2449 | func ObjectString(obj Object, qf Qualifier) string
2450 | func TypeString(typ Type, qf Qualifier) string
2451 | func SelectionString(s *Selection, qf Qualifier) string
2452 |
2453 | type Qualifier func(*Package) string
2454 |
2455 |
2456 | The `TypeString`, `ObjectString`, and `SelectionString`
2457 | functions are like the `String` methods of the respective types,
2458 | but they accept an additional argument, a `Qualifier`.
2459 |
2460 |
2461 |
2462 | A `Qualifier` is a client-provided function that determines how a
2463 | package name is rendered as a string.
2464 | If it is nil, the default behavior is to print the package's
2465 | path, just like the `String` methods do.
2466 | If a caller passes `(*Package).Name` as the qualifier, that is, a
2467 | function that accepts a package and returns its `Name`, then
2468 | objects are qualified only by the package name.
2469 | The above examples would look like this:
2470 |
2471 |
2472 | []json.Marshaler
2473 | json.Marshal
2474 | (*json.Encoder).Encode
2475 | func (enc *json.Encoder) Encode(v interface{}) error
2476 | func NewEncoder(w io.Writer) *json.Encoder
2477 |
2478 |
2479 | Often when a tool prints some output, it is implicitly in the
2480 | context of a particular package, perhaps one specified by the
2481 | command line or HTTP request.
2482 | In that case, it is more natural to omit the package qualification
2483 | altogether for objects belonging to that package, but to qualify all
2484 | other objects by their package's path.
2485 | That's what the `RelativeTo(pkg)` qualifier does:
2486 |
2487 |
2488 | func RelativeTo(pkg *Package) Qualifier
2489 |
2490 |
2491 | The examples below show how `json.NewEncoder` would be printed
2492 | using three qualifiers, each relative to a different package:
2493 |
2494 |
2495 | // RelativeTo "encoding/json":
2496 | func NewEncoder(w io.Writer) *Encoder
2497 |
2498 | // RelativeTo "io":
2499 | func NewEncoder(w Writer) *encoding/json.Encoder
2500 |
2501 | // RelativeTo any other package:
2502 | func NewEncoder(w io.Writer) *encoding/json.Encoder
2503 |
2504 |
2505 | Another qualifier that may be relevant to refactoring tools (but is
2506 | not currently provided by the type checker) is one that renders each
2507 | package name using the locally appropriate name within a given source
2508 | file.
2509 | Its behavior would depend on the set of import declarations, including
2510 | renaming imports, within that source file.
2511 |
2512 |
2513 |
2514 | # Getting from A to B
2515 |
2516 |
2517 | The type checker and its related packages represent many aspects of a
2518 | Go program in many different ways, and analysis tools must often map
2519 | between them.
2520 | For instance, a named entity may be identified by its `Object`;
2521 | by its declaring identifier (`ast.Ident`) or by any referring
2522 | identifier; by its declaring `ast.Node`; by the position
2523 | (`token.Pos`) of any those nodes; or by the filename and
2524 | line/column number (or byte offset) of those `token.Pos` values.
2525 |
2526 |
2527 |
2528 | In this section, we'll list solutions to a number of common problems
2529 | of the form "I have an A; I need the corresponding B".
2530 |
2531 |
2532 |
2533 | To map **from a `token.Pos` to an `ast.Node`**, call the
2534 | helper function
2535 | [`astutil.PathEnclosingInterval`](https://pkg.go.dev/golang.org/x/tools/go/ast/astutil#PathEnclosingInterval).
2536 | It returns the enclosing `ast.Node`, and all its ancestors up to
2537 | the root of the file.
2538 | You must know which file `*ast.File` the `token.Pos` belongs to.
2539 | Alternatively, you can search an entire program loaded by the
2540 | `loader` package, using
2541 | [`(*loader.Program).PathEnclosingInterval`](https://pkg.go.dev/golang.org/x/tools/go/loader#Program.PathEnclosingInterval).
2542 |
2543 |
2544 |
2545 | To map **from an `Object` to its declaring syntax**, call
2546 | `Pos` to get its position, then use `PathEnclosingInterval` as before.
2547 | This approach is suitable for a one-off query. For repeated use, it
2548 | may be more efficient to visit the syntax tree and construct the
2549 | mapping between declarations and objects.
2550 |
2551 |
2552 |
2553 | To map **from an `ast.Ident` to the `Object`** it refers to (or
2554 | declares), consult the `Uses` or `Defs` map for the
2555 | package, as shown in [Identifier Resolution](#identifier-resolution).
2556 |
2557 |
2558 |
2559 | To map **from an `Object` to its documentation**, find the
2560 | object's declaration, and look at the attached `Doc` field.
2561 | You must have set the parser's `ParseComments` flag.
2562 | See the `doc` example in [Imports](#imports).
2563 |
--------------------------------------------------------------------------------
/gotypes/defsuses/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "go/ast"
6 | "go/importer"
7 | "go/parser"
8 | "go/token"
9 | "go/types"
10 | "log"
11 | )
12 |
13 | const hello = `package main
14 |
15 | import "fmt"
16 |
17 | func main() {
18 | fmt.Println("Hello, world")
19 | }
20 | `
21 |
22 | // !+
23 | func PrintDefsUses(fset *token.FileSet, files ...*ast.File) error {
24 | conf := types.Config{Importer: importer.Default()}
25 | info := &types.Info{
26 | Defs: make(map[*ast.Ident]types.Object),
27 | Uses: make(map[*ast.Ident]types.Object),
28 | }
29 | _, err := conf.Check("hello", fset, files, info)
30 | if err != nil {
31 | return err // type error
32 | }
33 |
34 | for id, obj := range info.Defs {
35 | fmt.Printf("%s: %q defines %v\n",
36 | fset.Position(id.Pos()), id.Name, obj)
37 | }
38 | for id, obj := range info.Uses {
39 | fmt.Printf("%s: %q uses %v\n",
40 | fset.Position(id.Pos()), id.Name, obj)
41 | }
42 | return nil
43 | }
44 |
45 | //!-
46 |
47 | func main() {
48 | // Parse one file.
49 | fset := token.NewFileSet()
50 | f, err := parser.ParseFile(fset, "hello.go", hello, 0)
51 | if err != nil {
52 | log.Fatal(err) // parse error
53 | }
54 | if err := PrintDefsUses(fset, f); err != nil {
55 | log.Fatal(err) // type error
56 | }
57 | }
58 |
59 | /*
60 | //!+output
61 | $ go build golang.org/x/example/gotypes/defsuses
62 | $ ./defsuses
63 | hello.go:1:9: "main" defines
64 | hello.go:5:6: "main" defines func hello.main()
65 | hello.go:6:9: "fmt" uses package fmt
66 | hello.go:6:13: "Println" uses func fmt.Println(a ...interface{}) (n int, err error)
67 | //!-output
68 | */
69 |
--------------------------------------------------------------------------------
/gotypes/doc/main.go:
--------------------------------------------------------------------------------
1 | // The doc command prints the doc comment of a package-level object.
2 | package main
3 |
4 | import (
5 | "fmt"
6 | "go/ast"
7 | "go/parser"
8 | "log"
9 | "os"
10 |
11 | // TODO: these will use std go/types after Feb 2016
12 | "golang.org/x/tools/go/loader"
13 | "golang.org/x/tools/go/types/typeutil"
14 | )
15 |
16 | func main() {
17 | if len(os.Args) != 3 {
18 | log.Fatal("Usage: doc