├── 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 | [![Go Reference](https://pkg.go.dev/badge/golang.org/x/example.svg)](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 ") 19 | } 20 | //!+part1 21 | pkgpath, name := os.Args[1], os.Args[2] 22 | 23 | // The loader loads a complete Go program from source code. 24 | conf := loader.Config{ParserMode: parser.ParseComments} 25 | conf.Import(pkgpath) 26 | lprog, err := conf.Load() 27 | if err != nil { 28 | log.Fatal(err) // load error 29 | } 30 | 31 | // Find the package and package-level object. 32 | pkg := lprog.Package(pkgpath).Pkg 33 | obj := pkg.Scope().Lookup(name) 34 | if obj == nil { 35 | log.Fatalf("%s.%s not found", pkg.Path(), name) 36 | } 37 | //!-part1 38 | //!+part2 39 | 40 | // Print the object and its methods (incl. location of definition). 41 | fmt.Println(obj) 42 | for _, sel := range typeutil.IntuitiveMethodSet(obj.Type(), nil) { 43 | fmt.Printf("%s: %s\n", lprog.Fset.Position(sel.Obj().Pos()), sel) 44 | } 45 | 46 | // Find the path from the root of the AST to the object's position. 47 | // Walk up to the enclosing ast.Decl for the doc comment. 48 | _, path, _ := lprog.PathEnclosingInterval(obj.Pos(), obj.Pos()) 49 | for _, n := range path { 50 | switch n := n.(type) { 51 | case *ast.GenDecl: 52 | fmt.Println("\n", n.Doc.Text()) 53 | return 54 | case *ast.FuncDecl: 55 | fmt.Println("\n", n.Doc.Text()) 56 | return 57 | } 58 | } 59 | //!-part2 60 | } 61 | 62 | /* 63 | //!+output 64 | $ ./doc net/http File 65 | 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} 66 | /go/src/io/io.go:92:2: method (net/http.File) Close() error 67 | /go/src/io/io.go:71:2: method (net/http.File) Read(p []byte) (n int, err error) 68 | /go/src/net/http/fs.go:65:2: method (net/http.File) Readdir(count int) ([]os.FileInfo, error) 69 | /go/src/net/http/fs.go:66:2: method (net/http.File) Seek(offset int64, whence int) (int64, error) 70 | /go/src/net/http/fs.go:67:2: method (net/http.File) Stat() (os.FileInfo, error) 71 | 72 | A File is returned by a FileSystem's Open method and can be 73 | served by the FileServer implementation. 74 | 75 | The methods should behave the same as those on an *os.File. 76 | //!-output 77 | */ 78 | -------------------------------------------------------------------------------- /gotypes/go-types.md: -------------------------------------------------------------------------------- 1 | 2 | # `go/types`: The Go Type Checker 3 | 4 | This document is maintained by Alan Donovan `adonovan@google.com`. 5 | 6 | [October 2015 GothamGo talk on go/types](https://docs.google.com/presentation/d/13OvHYozAUBeISPRoLgG7kMBuja1NsU1D_mMlmbaYojk/view) 7 | 8 | 9 | # Contents 10 | 11 | %toc 12 | 13 | # Changes in Go 1.18 14 | 15 | Go 1.18 introduces generics, and several corresponding new APIs for `go/types`. 16 | This document is not yet up-to-date for these changes, but a guide to the new 17 | changes exists at 18 | [`x/exp/typeparams/example`](https://github.com/golang/exp/tree/master/typeparams/example). 19 | 20 | # Introduction 21 | 22 | 23 | The [`go/types` package]('https://golang.org/pkg/go/types) is a 24 | type-checker for Go programs, designed by Robert Griesemer. 25 | It became part of Go's standard library in Go 1.5. 26 | Measured by lines of code and by API surface area, it is one of the 27 | most complex packages in Go's standard library, and using it requires 28 | a firm grasp of the structure of Go programs. 29 | This tutorial will help you find your bearings. 30 | It comes with several example programs that you can obtain with `go get` and play with. 31 | We assume you are a proficient Go programmer who wants to build tools 32 | to analyze or manipulate Go programs and that you have some knowledge 33 | of how a typical compiler works. 34 | 35 | The type checker complements several existing 36 | standard packages for analyzing Go programs. 37 | We've listed them below. 38 | 39 | 40 | → go/types 41 | go/constant 42 | go/parser 43 | go/ast 44 | go/scanner 45 | go/token 46 | 47 | 48 | Starting at the bottom, the 49 | [`go/token` package](http://golang.org/pkg/go/token) 50 | defines the lexical tokens of Go. 51 | The [`go/scanner` package](http://golang.org/pkg/go/scanner) tokenizes an input stream and records 52 | file position information for use in diagnostics 53 | or for file surgery in a refactoring tool. 54 | The [`go/ast` package](http://golang.org/pkg/go/ast) 55 | defines the data types of the abstract syntax tree (AST). 56 | The [`go/parser` package](http://golang.org/pkg/go/parser) 57 | provides a robust recursive-descent parser that constructs the AST. 58 | And [`go/constant`](http://golang.org/pkg/go/constant) 59 | provides representations and arithmetic operations for the values of compile-time 60 | constant expressions, as we'll see in 61 | [Constants](#constants). 62 | 63 | 64 | 65 | The [`golang.org/x/tools/go/loader` package](https://pkg.go.dev/golang.org/x/tools/go/loader) 66 | from the `x/tools` repository is a client of the type 67 | checker that loads, parses, and type-checks a complete Go program from 68 | source code. 69 | We use it in some of our examples and you may find it useful too. 70 | 71 | 72 | 73 | The Go type checker does three main things. 74 | First, for every name in the program, it determines which declaration 75 | the name refers to; this is known as _identifier resolution_. 76 | Second, for every expression in the program, it determines what type 77 | that expression has, or reports an error if the expression has no 78 | type, or has an inappropriate type for its context; this is known as 79 | _type deduction_. 80 | Third, for every constant expression in the program, it determines the 81 | value of that constant; this is known as _constant evaluation_. 82 | 83 | 84 | 85 | Superficially, it appears that these three processes could be done 86 | sequentially, in the order above, but perhaps surprisingly, they must 87 | be done together. 88 | For example, the value of a constant may depend on the type of an 89 | expression due to operators like `unsafe.Sizeof`. 90 | Conversely, the type of an expression may depend on the value of a 91 | constant, since array types contain constants. 92 | As a result, type deduction and constant evaluation must be done 93 | together. 94 | 95 | 96 | 97 | As another example, we cannot resolve the identifier `k` in the composite 98 | literal `T{k: 0}` until we know whether `T` is a struct type. 99 | If it is, then `k` must be found among `T`'s fields. 100 | If not, then `k` is an ordinary reference 101 | to a constant or variable in the lexical environment. 102 | Consequently, identifier resolution and type deduction are also 103 | inseparable in the general case. 104 | 105 | 106 | 107 | Nonetheless, the three processes of identifier resolution, type 108 | deduction, and constant evaluation can be separated for the purpose of 109 | explanation. 110 | 111 | 112 | # An Example 113 | 114 | 115 | The code below shows the most basic use of the type checker to check 116 | the _hello, world_ program, supplied as a string. 117 | Later examples will be variations on this one, and we'll often omit 118 | boilerplate details such as parsing. 119 | To check out and build the examples, 120 | run `go get golang.org/x/example/gotypes/...`. 121 | 122 | 123 | %include pkginfo/main.go 124 | 125 | 126 | First, the program creates a 127 | [`token.FileSet`](http://golang.org/pkg/go/token/#FileSet). 128 | To avoid the need to store file names and line and column 129 | numbers in every node of the syntax tree, the `go/token` package 130 | provides `FileSet`, a data structure that stores this information 131 | compactly for a sequence of files. 132 | A `FileSet` records each file name only once, and records 133 | only the byte offsets of each newline, allowing a position within 134 | any file to be identified using a small integer called a 135 | `token.Pos`. 136 | Many tools create a single `FileSet` at startup. 137 | Any part of the program that needs to convert a `token.Pos` into 138 | an intelligible location---as part of an error message, for 139 | instance---must have access to the `FileSet`. 140 | 141 | 142 | 143 | Second, the program parses the input string. 144 | More realistic packages contain several source files, so the parsing 145 | step must be repeated for each one, or better, done in parallel. 146 | Third, it creates a `Config` that specifies type-checking options. 147 | Since the _hello, world_ program uses imports, we must indicate 148 | how to locate the imported packages. 149 | Here we use `importer.Default()`, which loads compiler-generated 150 | export data, but we'll explore alternatives in [Imports](#imports). 151 | 152 | 153 | 154 | Fourth, the program calls `Check`. 155 | This creates a `Package` whose path is `"cmd/hello"`, and 156 | type-checks each of the specified files---just one in this example. 157 | The final (nil) argument is a pointer to an optional `Info` 158 | struct that returns additional deductions from the type checker; more 159 | on that later. 160 | `Check` returns a `Package` even when it also returns an error. 161 | The type checker is robust to ill-formed input, 162 | and goes to great lengths to report accurate 163 | partial information even in the vicinity of syntax or type errors. 164 | `Package` has this definition: 165 | 166 | 167 | type Package struct{ ... } 168 | func (*Package) Path() string 169 | func (*Package) Name() string 170 | func (*Package) Scope() *Scope 171 | func (*Package) Imports() []*Package 172 | 173 | 174 | Finally, the program prints the attributes of the package, shown below. 175 | (The hexadecimal number may vary from one run to the next.) 176 | 177 | 178 | %include pkginfo/main.go output - 179 | 180 | 181 | A package's `Path`, such as `"encoding/json"`, is the string 182 | by which import declarations identify it. 183 | It is unique within a `$GOPATH` workspace, 184 | and for published packages it must be globally unique. 185 | 186 | 187 | A package's `Name` is the identifier in the `package` 188 | declaration of each source file within the package, such as `json`. 189 | The type checker reports an error if not all the package declarations in 190 | the package agree. 191 | The package name determines how the package is known when it is 192 | imported into a file (unless a renaming import is used), 193 | but is otherwise not visible to a program. 194 | 195 | 196 | `Scope` returns the package's [_lexical block_](#scopes), 197 | which provides access to all the named entities or 198 | [_objects_](#objects) declared at package level. 199 | `Imports` returns the set of packages directly imported by this 200 | one, and may be useful for computing dependencies 201 | ([Initialization Order](#initialization-order)). 202 | 203 | 204 | 205 | # Objects 206 | 207 | 208 | The task of identifier resolution is to map every identifier in the 209 | syntax tree, that is, every `ast.Ident`, to an object. 210 | For our purposes, an _object_ is a named entity created by a 211 | declaration, such as a `var`, `type`, or `func` 212 | declaration. 213 | (This is different from the everyday meaning of object in 214 | object-oriented programming.) 215 | 216 | 217 | 218 | Objects are represented by the `Object` interface: 219 | 220 | 221 | type Object interface { 222 | Name() string // package-local object name 223 | Exported() bool // reports whether the name starts with a capital letter 224 | Type() Type // object type 225 | Pos() token.Pos // position of object identifier in declaration 226 | 227 | Parent() *Scope // scope in which this object is declared 228 | Pkg() *Package // nil for objects in the Universe scope and labels 229 | Id() string // object id (see Ids section below) 230 | } 231 | 232 | 233 | The first four methods are straightforward; we'll explain the other 234 | three later. 235 | `Name` returns the object's name---an identifier. 236 | `Exported` is a convenience method that reports whether the first 237 | letter of `Name` is a capital, indicating that the object may be 238 | visible from outside the package. 239 | It's a shorthand for `ast.IsExported(obj.Name())`. 240 | `Type` returns the object's type; we'll come back to that in 241 | [Types](#types). 242 | 243 | 244 | 245 | `Pos` returns the source position of the object's declaring identifier. 246 | To make sense of a `token.Pos`, we need to call the 247 | `(*token.FileSet).Position` method, which returns a struct with 248 | individual fields for the file name, line number, column, and byte 249 | offset, though usually we just call its `String` method: 250 | 251 | 252 | fmt.Println(fset.Position(obj.Pos())) // "hello.go:10:6" 253 | 254 | 255 | Not all objects carry position information. 256 | Since the file format for compiler export data ([Imports](#imports)) 257 | does not record position information, calling `Pos` on an object 258 | imported from such a file returns zero, also known as 259 | `token.NoPos`. 260 | 261 | 262 | 263 | There are eight kinds of objects in the Go type checker. 264 | Most familiar are the kinds that can be declared at package level: 265 | constants, variables, functions, and types. 266 | Less familiar are statement labels, imported package names 267 | (such as `json` in a file containing an `import "encoding/json"` 268 | declaration), built-in functions (such as `append` and 269 | `len`), and the pre-declared `nil`. 270 | The eight types shown below are the only concrete types that satisfy 271 | the `Object` interface. 272 | In other words, `Object` is a _discriminated union_ of 8 273 | possible types, and we commonly use a type switch to distinguish them. 274 | 275 | 276 | Object = *Func // function, concrete method, or abstract method 277 | | *Var // variable, parameter, result, or struct field 278 | | *Const // constant 279 | | *TypeName // type name 280 | | *Label // statement label 281 | | *PkgName // package name, e.g. json after import "encoding/json" 282 | | *Builtin // predeclared function such as append or len 283 | | *Nil // predeclared nil 284 | 285 | 286 | `Object`s are canonical. 287 | That is, two `Object`s `x` and `y` denote the same 288 | entity if and only if `x==y`. 289 | Object identity is significant, and objects are routinely compared by 290 | the addresses of the underlying pointers. 291 | Although a package-level object is uniquely identified by its name 292 | and enclosing package, for other objects there is no simple way to 293 | obtain a string that uniquely identifies it. 294 | 295 | 296 | 297 | The `Parent` method returns the `Scope` (lexical block) in 298 | which the object was declared; we'll come back to this in 299 | [Scopes](#scopes). 300 | Fields and methods are not found in the lexical environment, so 301 | their objects have no `Parent`. 302 | 303 | 304 | 305 | 306 | The `Pkg` method returns the `Package` to which this object 307 | belongs, even for objects not declared at package level. 308 | Only predeclared objects have no package. 309 | The `Id` method will be explained in [Ids](#ids). 310 | 311 | 312 | 313 | Not all methods make sense for each kind of object. For instance, 314 | the last four kinds above have no meaningful `Type` method. 315 | And some kinds of objects have methods in addition to those required by the 316 | `Object` interface: 317 | 318 | 319 | func (*Func) Scope() *Scope 320 | func (*Var) Anonymous() bool 321 | func (*Var) IsField() bool 322 | func (*Const) Val() constant.Value 323 | func (*TypeName) IsAlias() bool 324 | func (*PkgName) Imported() *Package 325 | 326 | 327 | `(*Func).Scope` returns the [lexical block](#scopes) 328 | containing the function's parameters, results, 329 | and other local declarations. 330 | `(*Var).IsField` distinguishes struct fields from ordinary 331 | variables, and `(*Var).Anonymous` discriminates named fields like 332 | the one in `struct{T T}` from anonymous fields like the one in `struct{T}`. 333 | `(*Const).Val` returns the value of a named [constant](#constants). 334 | 335 | 336 | `(*TypeName).IsAlias`, introduced in Go 1.9, reports whether the 337 | type name is simply an alias for a type (as in `type I = int`), 338 | as opposed to a definition of a [`Named`](#named-types) type, as 339 | in `type Celsius float64`. 340 | 341 | 342 | `(*PkgName).Imported` returns the package (for instance, 343 | `encoding/json`) denoted by a given import name such as `json`. 344 | Each time a package is imported, a new `PkgName` object is 345 | created, usually with the same name as the `Package` it 346 | denotes, but not always, as in the case of a renaming import. 347 | `PkgName`s are objects, but `Package`s are not. 348 | We'll look more closely at this in [Imports](#imports). 349 | 350 | 351 | 352 | All relationships between the syntax trees (`ast.Node`s) and type 353 | checker data structures such as `Object`s and `Type`s are 354 | stored in mappings outside the syntax tree itself. 355 | Be aware that the `go/ast` package also defines a type called 356 | `Object` that resembles---and predates---the type checker's 357 | `Object`, and that `ast.Object`s are held directly by 358 | identifiers in the AST. 359 | They are created by the parser, which has a necessarily limited view 360 | of the package, so the information they represent is at best partial and 361 | in some cases wrong, as in the `T{k: 0}` example mentioned above. 362 | If you are using the type checker, there is no reason to use the older 363 | `ast.Object` mechanism. 364 | 365 | 366 | 367 | # Identifier Resolution 368 | 369 | 370 | Identifier resolution computes the relationship between 371 | identifiers and objects. 372 | Its results are recorded in the `Info` struct optionally passed 373 | to `Check`. 374 | The fields related to identifier resolution are shown below. 375 | 376 | 377 | type Info struct { 378 | Defs map[*ast.Ident]Object 379 | Uses map[*ast.Ident]Object 380 | Implicits map[ast.Node]Object 381 | Selections map[*ast.SelectorExpr]*Selection 382 | Scopes map[ast.Node]*Scope 383 | ... 384 | } 385 | 386 | 387 | Since not all facts computed by the type checker are needed by every 388 | client, the API lets clients control which components of the result 389 | should be recorded and which discarded: only fields that hold a 390 | non-nil map will be populated during the call to `Check`. 391 | 392 | 393 | 394 | The two fields of type `map[*ast.Ident]Object` are the most important: 395 | `Defs` records _declaring_ identifiers and 396 | `Uses` records _referring_ identifiers. 397 | In the example below, the comments indicate which identifiers are of 398 | which kind. 399 | 400 | 401 | var x int // def of x, use of int 402 | fmt.Println(x) // uses of fmt, Println, and x 403 | type T struct{U} // def of T, use of U (type), def of U (field) 404 | 405 | 406 | The final line above illustrates why we don't combine `Defs` and 407 | `Uses` into one map. 408 | In the anonymous field declaration `struct{U}`, the 409 | identifier `U` is both a use of the type `U` (a 410 | `TypeName`) and a definition of the anonymous field (a 411 | `Var`). 412 | 413 | 414 | 415 | The function below prints the location of each referring and defining 416 | identifier in the input program, and the object it refers to. 417 | 418 | 419 | %include defsuses/main.go 420 | 421 | 422 | Let's use the _hello, world_ program again as the input: 423 | 424 | 425 | %include hello/hello.go 426 | 427 | 428 | This is what it prints: 429 | 430 | 431 | %include defsuses/main.go output - 432 | 433 | 434 | Notice that the `Defs` mapping may contain nil entries in a few 435 | cases. 436 | The first line of output reports that the package identifier 437 | `main` is present in the `Defs` mapping, but has no 438 | associated object. 439 | 440 | 441 | 442 | The `Implicits` mapping handles two cases of the syntax in 443 | which an `Object` is declared without an `ast.Ident`, namely type 444 | switches and import declarations. 445 | 449 | In the type switch below, which declares a local variable `y`, 450 | the type of `y` is different in each case of the switch: 451 | 452 | 453 | switch y := x.(type) { 454 | case int: 455 | fmt.Printf("%d", y) 456 | case string: 457 | fmt.Printf("%q", y) 458 | default: 459 | fmt.Print(y) 460 | } 461 | 462 | 463 | To represent this, for each single-type case, the type checker creates 464 | a separate `Var` object for `y` with the appropriate type, 465 | and `Implicits` maps each `ast.CaseClause` to the `Var` 466 | for that case. 467 | The `default` case, the `nil` case, and cases with more than one 468 | type all use the regular `Var` object that is associated with the 469 | identifier `y`, which is found in the `Defs` mapping. 470 | 471 | 472 | 473 | The import declaration below defines the name `json` without an 474 | `ast.Ident`: 475 | 476 | 477 | import "encoding/json" 478 | 479 | 480 | `Implicits` maps this `ast.ImportSpec` to the `PkgName` 481 | object named `json` that it implicitly declares. 482 | 483 | 484 | 485 | The `Selections` mapping, of type 486 | `map[*ast.SelectorExpr]*Selection`, records the meaning of each 487 | expression of the form _`expr`_`.f`, where _`expr`_ is 488 | an expression or type and `f` is the name of a field or method. 489 | These expressions, called _selections_, are represented by 490 | `ast.SelectorExpr` nodes in the AST. 491 | We'll talk more about the `Selection` type in [Selections](#selections). 492 | 493 | 494 | 495 | Not all `ast.SelectorExpr` nodes represent selections. 496 | Expressions like `fmt.Println`, in which a package name precedes 497 | the dot, are _qualified identifiers_. 498 | They do not appear in the `Selections` mapping, but their 499 | constituent identifiers (such as `fmt` and `Println`) both 500 | appear in `Uses`. 501 | 502 | 503 | 504 | Referring identifiers that are not part of an `ast.SelectorExpr` 505 | are _lexical references_. 506 | That is, they are resolved to an object by searching for the 507 | innermost enclosing lexical declaration of that name. 508 | We'll see how that search works in the next section. 509 | 510 | 511 | # Scopes 512 | 513 | 514 | The `Scope` type is a mapping from names to objects. 515 | 516 | 517 | type Scope struct{ ... } 518 | 519 | func (s *Scope) Names() []string 520 | func (s *Scope) Lookup(name string) Object 521 | 522 | 523 | `Names` returns the set of names in the mapping, in sorted order. 524 | (It is not a simple accessor though, so call it sparingly.) 525 | The `Lookup ` method returns the object for a given name, so we 526 | can print all the entries or _bindings_ in a scope like this: 527 | 528 | 529 | for _, name := range scope.Names() { 530 | fmt.Println(scope.Lookup(name)) 531 | } 532 | 533 | 534 | The _scope_ of a declaration of a name is the region of 535 | program source in which a reference to the name resolves to that 536 | declaration. That is, scope is a property of a declaration. 537 | However, in the `go/types` API, the `Scope` type represents 538 | a _lexical block_, which is one component of the lexical 539 | environment. 540 | Consider the _hello, world_ program again: 541 | 542 | 543 | package main 544 | 545 | import "fmt" 546 | 547 | func main() { 548 | const message = "hello, world" 549 | fmt.Println(message) 550 | } 551 | 552 | 553 | There are four lexical blocks in this program. 554 | The outermost one is the _universe block_, which maps the 555 | pre-declared names like `int`, `true`, and `append` to 556 | their objects---a `TypeName`, a `Const`, and a 557 | `Builtin`, respectively. 558 | The universe block is represented by the global variable 559 | `Universe`, of type `*Scope`, although it's logically a 560 | constant so you shouldn't modify it. 561 | 562 | 563 | 564 | Next is the _package block_, which maps `"main"` to the 565 | `main` function. 566 | Following that is the _file block_, which maps `"fmt"` to 567 | the `PkgName` object for this import of the `fmt` package. 568 | And finally, the innermost block is that of function `main`, a 569 | local block, which contains the declaration of `message`, a `Const`. 570 | The `main` function is trivial, but many functions contain 571 | several blocks since each `if`, `for`, `switch`, 572 | `case`, or `select` statement creates at least one 573 | additional block. 574 | Local blocks nest to arbitrary depths. 575 | 576 | 577 | 578 | The structure of the lexical environment thus forms a tree, with the 579 | universe block at the root, the package blocks beneath it, the file 580 | blocks beneath them, and then any number of local blocks beneath the 581 | files. 582 | We can access and navigate this tree structure with the following 583 | methods of `Scope`: 584 | 585 | 586 | func (s *Scope) Parent() *Scope 587 | func (s *Scope) NumChildren() int 588 | func (s *Scope) Child(i int) *Scope 589 | 590 | 591 | `Parent` lets us walk up the tree, and `Child` 592 | lets us walk down it. 593 | Note that although the `Parent` of every package `Scope` is 594 | `Universe`, `Universe` has no children. 595 | This asymmetry is a consequence of using a global variable to hold 596 | `Universe`. 597 | 598 | 599 | 600 | To obtain the universe block, we use the `Universe` global variable. 601 | To obtain the lexical block of a `Package`, we call its 602 | `Scope` method. 603 | To obtain the scope of a file (`*ast.File`), or any smaller piece 604 | of syntax such as an `*ast.IfStmt`, we consult the `Scopes` 605 | mapping in the `Info` struct, which maps each block-creating 606 | syntax node to its block. 607 | The lexical block of a named function or method can also be obtained 608 | by calling its `(*Func).Scope` method. 609 | 610 | 611 | 616 | 617 | 618 | To look up a name in the lexical environment, we must search the tree 619 | of lexical blocks, starting at a particular `Scope` and walking 620 | up to the root until a declaration of the name is found. 621 | For convenience, the `LookupParent` method does this, returning 622 | not just the object, if found, but also the `Scope` in which it was 623 | declared, which may be an ancestor of the initial one: 624 | 625 | 626 | func (s *Scope) LookupParent(name string, pos token.Pos) (*Scope, Object) 627 | 628 | 629 | The `pos` parameter determines the position in the source code at 630 | which the name should be resolved. 631 | The effective lexical environment is different at each point in the 632 | block because it depends on which local declarations appear 633 | before or after that point. 634 | (We'll see an illustration in a moment.) 635 | 636 | 637 | 638 | `Scope` has several other methods relating to source positions: 639 | 640 | 641 | func (s *Scope) Pos() token.Pos 642 | func (s *Scope) End() token.Pos 643 | func (s *Scope) Contains(pos token.Pos) bool 644 | func (s *Scope) Innermost(pos token.Pos) *Scope 645 | 646 | 647 | `Pos` and `End` report the `Scope`'s start and end 648 | position which, for explicit blocks, coincide with its curly 649 | braces. 650 | `Contains` is a convenience method that reports whether a 651 | position lies in this interval. 652 | `Innermost` returns the innermost scope containing the specified 653 | position, which may be a child or other descendent of the initial 654 | scope. 655 | 656 | 657 | 658 | These features are useful for tools that wish to resolve names or 659 | evaluate constant expressions as if they had appeared at a particular 660 | point within the program. 661 | The next example program finds all the comments in the input, 662 | treating the contents of each one as a name. It looks up each name in 663 | the environment at the position of the comment, and prints what it 664 | finds. 665 | Observe that the `ParseComments` flag directs the parser to 666 | preserve comments in the input. 667 | 668 | 669 | %include lookup/lookup.go main 670 | 671 | 672 | The expression `pkg.Scope().Innermost(pos)` finds the innermost 673 | `Scope` that encloses the comment, and `LookupParent(name, pos)` 674 | does a name lookup at a specific position in that lexical block. 675 | 676 | 677 | 678 | A typical input is shown below. 679 | The first comment causes a lookup of `"append"` in the file block. 680 | The second comment looks up `"fmt"` in the `main` function's block, 681 | and so on. 682 | 683 | 684 | %include lookup/lookup.go input - 685 | 686 | 687 | Here's the output: 688 | 689 | 690 | %include lookup/lookup.go output - 691 | 692 | 693 | Notice how the two lookups of `main` return different results, 694 | even though they occur in the same block, because one precedes the 695 | declaration of the local variable named `main` and the other 696 | follows it. 697 | Also notice that there are two lookups of the name `x` but only 698 | the first one, in the function block, succeeds. 699 | 700 | 701 | 702 | Download the program and modify both the input program and 703 | the set of comments to get a better feel for how name resolution works. 704 | 705 | 706 | 707 | The table below summarizes which kinds of objects may be declared at 708 | each level of the tree of lexical blocks. 709 | 710 | 711 | Universe File Package Local 712 | Builtin ✔ 713 | Nil ✔ 714 | Const ✔ ✔ ✔ 715 | TypeName ✔ ✔ ✔ 716 | Func ✔ 717 | Var ✔ ✔ 718 | PkgName ✔ 719 | Label ✔ 720 | 721 | 722 | # Initialization Order 723 | 724 | 725 | In the course of identifier resolution, the type checker constructs a 726 | graph of references among declarations of package-level variables and 727 | functions. 728 | The type checker reports an error if the initializer expression for a 729 | variable refers to that variable, whether directly or indirectly. 730 | 731 | 732 | 733 | The reference graph determines the initialization order of the 734 | package-level variables, as required by the Go spec, using a 735 | breadth-first algorithm. 736 | First, variables in the graph with no successors are removed, sorted 737 | into the order in which they appear in the source code, then added 738 | to a list. This creates more variables that have no successors. 739 | The process repeats until they have all been removed. 740 | 741 | 742 | 743 | The result is available in the `InitOrder` field of the 744 | `Info` struct, whose type is `[]Initializer`. 745 | 746 | 747 | type Info struct { 748 | ... 749 | InitOrder []Initializer 750 | ... 751 | } 752 | 753 | type Initializer struct { 754 | Lhs []*Var // var Lhs = Rhs 755 | Rhs ast.Expr 756 | } 757 | 758 | 759 | Each element of the list represents a single initializer expression 760 | that must be executed, and the variables to which it is assigned. 761 | The variables may number zero, one, or more, as in these examples: 762 | 763 | 764 | var _ io.Writer = new(bytes.Buffer) 765 | var rx = regexp.MustCompile("^b(an)*a$") 766 | var cwd, cwdErr = os.Getwd() 767 | 768 | 769 | This process governs the initialization order of variables within a 770 | package. 771 | Across packages, dependencies must be initialized first, although the 772 | order among them is not specified. 773 | That is, any topological order of the import graph will do. 774 | The `(*Package).Imports` method returns the set of direct 775 | dependencies of a package. 776 | 777 | 778 | # Types 779 | 780 | 781 | The main job of the type checker is, of course, to deduce the type 782 | of each expression and to report type errors. 783 | Like `Object`, `Type` is an interface type used as a 784 | discriminated union of several concrete types but, unlike 785 | `Object`, `Type` has very few methods because types have 786 | little in common with each other. 787 | Here is the interface: 788 | 789 | 790 | type Type interface { 791 | Underlying() Type 792 | } 793 | 794 | 795 | And here are the eleven concrete types that satisfy it: 796 | 797 | 798 | Type = *Basic 799 | | *Pointer 800 | | *Array 801 | | *Slice 802 | | *Map 803 | | *Chan 804 | | *Struct 805 | | *Tuple 806 | | *Signature 807 | | *Named 808 | | *Interface 809 | 810 | 811 | With the exception of `Named` types, instances of `Type` are 812 | not canonical. 813 | That is, it is usually a mistake to compare types using `t1==t2` 814 | since this equivalence is not the same as the 815 | [type identity relation](https://golang.org/ref/spec#Type_identity) 816 | defined by the Go spec. 817 | Use this function instead: 818 | 819 | 820 | func Identical(t1, t2 Type) bool 821 | 822 | 823 | For the same reason, you should not use a `Type` as a key in a map. 824 | The [`golang.org/x/tools/go/types/typeutil` package](https://pkg.go.dev/golang.org/x/tools/go/types/typeutil) 825 | provides a map keyed by types that uses the correct 826 | equivalence relation. 827 | 828 | 829 | The Go spec defines three relations over types. 830 | [_Assignability_](https://golang.org/ref/spec#Assignability) 831 | governs which pairs of types may appear on the 832 | left- and right-hand side of an assignment, including implicit 833 | assignments such as function calls, map and channel operations, and so 834 | on. 835 | [_Comparability_](https://golang.org/ref/spec#Comparison_operators) 836 | determines which types may appear in a comparison `x==y` or a 837 | switch case or may be used as a map key. 838 | [_Convertibility_](https://golang.org/ref/spec#Conversions) 839 | governs which pairs of types are allowed in a conversion operation 840 | `T(v)`. 841 | You can query these relations with the following predicate functions: 842 | 843 | 844 | func AssignableTo(V, T Type) bool 845 | func Comparable(T Type) bool 846 | func ConvertibleTo(V, T Type) bool 847 | 848 | 849 | Let's take a look at each kind of type. 850 | 851 | 852 | ## Basic types 853 | 854 | 855 | `Basic` represents all types that are not composed from simpler 856 | types. 857 | This is essentially the set of underlying types that a constant expression is 858 | permitted to have--strings, booleans, and numbers---but it also 859 | includes `unsafe.Pointer` and untyped nil. 860 | 861 | 862 | type Basic struct{...} 863 | func (*Basic) Kind() BasicKind 864 | func (*Basic) Name() string 865 | func (*Basic) Info() BasicInfo 866 | 867 | 868 | The `Kind` method returns an "enum" value that indicates which 869 | basic type this is. 870 | The kinds `Bool`, `String`, `Int16`, and so on, 871 | represent the corresponding predeclared boolean, string, or numeric 872 | types. 873 | There are two synonyms: `Byte` is equivalent to `Uint8` 874 | and `Rune` is equivalent to `Int32`. 875 | The kind `UnsafePointer` represents `unsafe.Pointer`. 876 | The kinds `UntypedBool`, `UntypedInt` and so on represent 877 | the six kinds of "untyped" constant types: boolean, integer, rune, 878 | float, complex, and string. 879 | The kind `UntypedNil` represents the type of the predeclared 880 | `nil` value. 881 | And the kind `Invalid` indicates the invalid type, which is used 882 | for expressions containing errors, or for objects without types, like 883 | `Label`, `Builtin`, or `PkgName`. 884 | 885 | 886 | 887 | The `Name` method returns the name of the type, such as 888 | `"float64"`, and the `Info` method returns a bitfield that 889 | encodes information about the type, such as whether it is signed or 890 | unsigned, integer or floating point, or real or complex. 891 | 892 | 893 | 894 | `Typ` is a table of canonical basic types, indexed by 895 | kind, so `Typ[String]` returns the `*Basic` that represents 896 | `string`, for instance. 897 | Like `Universe`, `Typ` is logically a constant, so don't 898 | modify it. 899 | 900 | 901 | 902 | A few minor subtleties: 903 | According to the Go spec, pre-declared types such as `int` are 904 | named types for the purposes of assignability, even though the type 905 | checker does not represent them using `Named`. 906 | And `unsafe.Pointer` is a pointer type for the purpose of 907 | determining whether the receiver type of a method is legal, even 908 | though the type checker does not represent it using `Pointer`. 909 | 910 | 911 | 912 | The "untyped" types are usually only ascribed to constant expressions, 913 | but there is one exception. 914 | A comparison `x==y` has type "untyped bool", so the result of 915 | this expression may be assigned to a variable of type `bool` or 916 | any other named boolean type. 917 | 918 | 919 | 920 | ## Simple Composite Types 921 | 922 | 923 | The types `Pointer`, `Array`, `Slice`, `Map`, 924 | and `Chan` are pretty self-explanatory. 925 | All have an `Elem` method that returns the element type `T` 926 | for a pointer `*T`, an array `[n]T`, a slice `[]T`, a 927 | map `map[K]T`, or a channel `chan T`. 928 | This should feel familiar if you've used the `reflect.Value` API. 929 | 930 | 931 | 932 | In addition, the `*Map`, `*Chan`, and `*Array` types 933 | have accessor methods that return their key type, direction, and 934 | length, respectively: 935 | 936 | 937 | func (*Map) Key() Type 938 | func (*Chan) Dir() ChanDir // = Send | Recv | SendRecv 939 | func (*Array) Len() int64 940 | 941 | 942 | 943 | ## Struct Types 944 | 945 | 946 | A struct type has an ordered list of fields and a corresponding 947 | ordered list of field tags. 948 | 949 | 950 | type Struct struct{ ... } 951 | func (*Struct) NumFields() int 952 | func (*Struct) Field(i int) *Var 953 | func (*Struct) Tag(i int) string 954 | 955 | 956 | Each field is a `Var` object whose `IsField` method returns true. 957 | Field objects have no `Parent` scope, because they are 958 | resolved through selections, not through the lexical environment. 959 | 960 | 961 | 962 | 963 | Thanks to embedding, the expression `new(S).f` may be a shorthand 964 | for a longer expression such as `new(S).d.e.f`, but in the 965 | representation of `Struct` types, these field selection 966 | operations are explicit. 967 | That is, the set of fields of struct type `S` does not include `f`. 968 | An anonymous field is represented like a regular field, but its 969 | `Anonymous` method returns true. 970 | 971 | 972 | 973 | One subtlety is relevant to tools that generate documentation. 974 | When analyzing a declaration such as this, 975 | 976 | 977 | type T struct{x int} 978 | 979 | 980 | it may be tempting to consider the `Var` object for field `x` as if it 981 | had the name `"T.x"`, but beware: field objects do not have 982 | canonical names and there is no way to obtain the name `"T"` 983 | from the `Var` for `x`. 984 | That's because several types may have the same underlying struct type, 985 | as in this code: 986 | 987 | 988 | type T struct{x int} 989 | type U T 990 | 991 | 992 | Here, the `Var` for field `x` belongs equally to `T` 993 | and to `U`, and short of inspecting source positions or walking 994 | the AST---neither of which is possible for objects loaded from compiler 995 | export data---it is not possible to ascertain that `x` was declared as 996 | part of `T`. 997 | The type checker builds the exact same data structures given this input: 998 | 999 | 1000 | type T U 1001 | type U struct{x int} 1002 | 1003 | 1004 | A similar issue applies to the methods of named interface types. 1005 | 1006 | 1007 | ## Tuple Types 1008 | 1009 | 1010 | Like a struct, a tuple type has an ordered list of fields, and fields 1011 | may be named. 1012 | 1013 | 1014 | type Tuple struct{ ... } 1015 | func (*Tuple) Len() int 1016 | func (*Tuple) At(i int) *Var 1017 | 1018 | 1019 | Although tuples are not the type of any variable in Go, they are 1020 | the type of some expressions, such as the right-hand sides of these 1021 | assignments: 1022 | 1023 | 1024 | v, ok = m[key] 1025 | v, ok = <-ch 1026 | v, ok = x.(T) 1027 | f, err = os.Open(filename) 1028 | 1029 | 1030 | Tuples also represent the types of the parameter list and the result 1031 | list of a function, as we will see. 1032 | 1033 | 1034 | 1035 | Since empty tuples are common, the nil `*Tuple` pointer is a valid empty tuple. 1036 | 1037 | 1038 | 1039 | ## Function and Method Types 1040 | 1041 | 1042 | The types of functions and methods are represented by a `Signature`, 1043 | which has a tuple of parameter types and a tuple of result types. 1044 | 1045 | 1046 | type Signature struct{ ... } 1047 | func (*Signature) Recv() *Var 1048 | func (*Signature) Params() *Tuple 1049 | func (*Signature) Results() *Tuple 1050 | func (*Signature) Variadic() bool 1051 | 1052 | 1053 | Variadic functions such as `fmt.Println` have the `Variadic` 1054 | flag set. 1055 | The final parameter of such functions is always a slice, or in the 1056 | special case of certain calls to `append`, a string. 1057 | 1058 | 1059 | 1060 | A `Signature` for a method, whether concrete or abstract, has a 1061 | non-nil receiver parameter, `Recv`. 1062 | The type of the receiver is usually a named type or a pointer to a named type, 1063 | but it may be an unnamed struct or interface type in some cases. 1064 | Method types are rather second-class: they are only used for the 1065 | `Func` objects created by method declarations, and no Go 1066 | expression has a method type. 1067 | When printing a method type, the receiver does not appear, and the 1068 | `Identical` predicate ignores the receiver. 1069 | 1070 | 1071 | 1072 | The types of `Builtin` objects like `append` cannot be 1073 | expressed as a `Signature` since those types require parametric 1074 | polymorphism. 1075 | `Builtin` objects are thus ascribed the `Invalid` basic type. 1076 | However, the type of each _call_ to a built-in function has a specific 1077 | and expressible Go type. 1078 | These types are recorded during type checking for later use 1079 | ([TypeAndValue](#typeandvalue)). 1080 | 1081 | 1082 | 1083 | ## Named Types 1084 | 1085 | 1086 | Type declarations come in two forms. 1087 | The simplest kind, introduced in Go 1.9, 1088 | merely declares a (possibly alternative) name for an existing type. 1089 | Type names used in this way are informally called _type aliases_. 1090 | For example, this declaration lets you use the type 1091 | `Dictionary` as an alias for `map[string]string`: 1092 | 1093 | type Dictionary = map[string]string 1094 | 1095 | The declaration creates a `TypeName` object for `Dictionary`. The 1096 | object's `IsAlias` method returns true, and its `Type` method returns 1097 | a `Map` type that represents `map[string]string`. 1098 | 1099 | 1100 | The second form of type declaration, and the only kind prior to Go 1101 | 1.9, does not use an equals sign: 1102 | 1103 | type Celsius float64 1104 | 1105 | This declaration does more than just give a name to a type. 1106 | It first defines a new `Named` type 1107 | whose underlying type is `float64`; this `Named` type is different 1108 | from any other type, including `float64`. The declaration binds the 1109 | `TypeName` object to the `Named` type. 1110 | 1111 | Since Go 1.9, the Go language specification has used the term _defined 1112 | types_ instead of named types; 1113 | the essential property of a defined type is not that it has a name, 1114 | but that it is a distinct type with its own method set. 1115 | However, the type checker API predates that 1116 | change and instead calls defined types "named" types. 1117 | 1118 | type Named struct{ ... } 1119 | func (*Named) NumMethods() int 1120 | func (*Named) Method(i int) *Func 1121 | func (*Named) Obj() *TypeName 1122 | func (*Named) Underlying() Type 1123 | 1124 | The `Named` type's `Obj` method returns the `TypeName` object, which 1125 | provides the name, position, and other properties of the declaration. 1126 | Conversely, the `TypeName` object's `Type` method returns the `Named` type. 1127 | 1128 | A `Named` type may appear as the receiver type in a method declaration. 1129 | Methods are associated with the `Named` type, not the name (the 1130 | `TypeName` object); it's possible---though cryptic---to declare a 1131 | method on a `Named` type using one of its aliases. 1132 | The `NumMethods` and `Method` methods enumerate the declared 1133 | methods associated with this `Named` type (or a pointer to it), 1134 | in the order they were declared. 1135 | However, due to the subtleties of anonymous fields and the difference 1136 | between value and pointer receivers, a named type may have more or fewer 1137 | methods than this list. We'll return to this in [Method Sets](#method-sets). 1138 | 1139 | 1140 | 1141 | Every `Type` has an `Underlying` method, but for all of them 1142 | except `*Named`, it is simply the identity function. 1143 | For a named type, `Underlying` returns its underlying type, which 1144 | is always an unnamed type. 1145 | Thus `Underlying` returns `int` for both `T` and 1146 | `U` below. 1147 | 1148 | 1149 | type T int 1150 | type U T 1151 | 1152 | 1153 | Clients of the type checker often use type assertions or type switches 1154 | with a `Type` operand. 1155 | When doing so, it is often necessary to switch on the type that 1156 | _underlies_ the type of interest, and failure to do so may be a 1157 | bug. 1158 | 1159 | This is a common pattern: 1160 | 1161 | 1162 | // handle types of composite literal 1163 | switch u := t.Underlying().(type) { 1164 | case *Struct: // ... 1165 | case *Map: // ... 1166 | case *Array, *Slice: // ... 1167 | default: 1168 | panic("impossible") 1169 | } 1170 | 1171 | ## Interface Types 1172 | 1173 | 1174 | Interface types are represented by `Interface`. 1175 | 1176 | 1177 | type Interface struct{ ... } 1178 | func (*Interface) Empty() bool 1179 | func (*Interface) NumMethods() int 1180 | func (*Interface) Method(i int) *Func 1181 | func (*Interface) NumEmbeddeds() int 1182 | func (*Interface) Embedded(i int) *Named 1183 | func (*Interface) NumExplicitMethods() int 1184 | func (*Interface) ExplicitMethod(i int) *Func 1185 | 1186 | 1187 | Syntactically, an interface type has a list of explicitly declared 1188 | methods (`ExplicitMethod`), and a list of embedded named 1189 | interface types (`Embedded`), but many clients care only about 1190 | the complete set of methods, which can be enumerated via 1191 | `Method`. 1192 | All three lists are ordered by name. 1193 | Since the empty interface is an important special case, the 1194 | `Empty` predicate provides a shorthand for `NumMethods() == 1195 | 0`. 1196 | 1197 | 1198 | 1199 | As with the fields of structs (see above), the methods of interfaces 1200 | may belong equally to more than one interface type. 1201 | The `Func` object for method `f` in the code below is shared 1202 | by `I` and `J`: 1203 | 1204 | 1205 | type I interface { f() } 1206 | type J I 1207 | 1208 | 1209 | Because the difference between interface (abstract) and 1210 | non-interface (concrete) types is so important in Go, the 1211 | `IsInterface` predicate is provided for convenience. 1212 | 1213 | 1214 | func IsInterface(Type) bool 1215 | 1216 | 1217 | The type checker provides three utility methods relating to interface 1218 | satisfaction: 1219 | 1220 | 1221 | func Implements(V Type, T *Interface) bool 1222 | func AssertableTo(V *Interface, T Type) bool 1223 | func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType bool) 1224 | 1225 | 1226 | The `Implements` predicate reports whether a type satisfies an 1227 | interface type. 1228 | `MissingMethod` is like `Implements`, but instead of 1229 | returning false, it explains why a type does not satisfy the 1230 | interface, for use in diagnostics. 1231 | 1232 | 1233 | 1234 | `AssertableTo` reports whether a type assertion `v.(T)` is legal. 1235 | If `T` is a concrete type that doesn't have all the methods of 1236 | interface `v`, then the type assertion is not legal, as in this example: 1237 | 1238 | 1239 | // error: io.Writer is not assertible to int 1240 | func f(w io.Writer) int { return w.(int) } 1241 | 1242 | 1243 | 1244 | ## TypeAndValue 1245 | 1246 | 1247 | The type checker records the type of each expression in another field 1248 | of the `Info` struct, namely `Types`: 1249 | 1250 | 1251 | type Info struct { 1252 | ... 1253 | Types map[ast.Expr]TypeAndValue 1254 | } 1255 | 1256 | 1257 | No entries are recorded for identifiers since the `Defs` and 1258 | `Uses` maps provide more information about them. 1259 | Also, no entries are recorded for pseudo-expressions like 1260 | `*ast.KeyValuePair` or `*ast.Ellipsis`. 1261 | 1262 | 1263 | 1264 | The value of the `Types` map is a `TypeAndValue`, which 1265 | (unsurprisingly) holds the type and value of the expression, and in 1266 | addition, its _mode_. 1267 | The mode is opaque, but has predicates to answer questions such as: 1268 | Does this expression denote a value or a type? Does this value have an 1269 | address? Does this expression appear on the left-hand side of an 1270 | assignment? Does this expression appear in a context that expects two 1271 | results? 1272 | The comments in the code below give examples of expressions that 1273 | satisfy each predicate. 1274 | 1275 | 1276 | type TypeAndValue struct { 1277 | Type Type 1278 | Value constant.Value // for constant expressions only 1279 | ... 1280 | } 1281 | 1282 | func (TypeAndValue) IsVoid() bool // e.g. "main()" 1283 | func (TypeAndValue) IsType() bool // e.g. "*os.File" 1284 | func (TypeAndValue) IsBuiltin() bool // e.g. "len(x)" 1285 | func (TypeAndValue) IsValue() bool // e.g. "*os.Stdout" 1286 | func (TypeAndValue) IsNil() bool // e.g. "nil" 1287 | func (TypeAndValue) Addressable() bool // e.g. "a[i]" but not "f()", "m[key]" 1288 | func (TypeAndValue) Assignable() bool // e.g. "a[i]", "m[key]" 1289 | func (TypeAndValue) HasOk() bool // e.g. "<-ch", "m[key]" 1290 | 1291 | 1292 | The statement below inspects every expression within the AST of a single 1293 | type-checked file and prints its type, value, and mode: 1294 | 1295 | 1296 | %include typeandvalue/main.go inspect 1297 | 1298 | 1299 | It makes use of these two helper functions, which are not shown: 1300 | 1301 | 1302 | // nodeString formats a syntax tree in the style of gofmt. 1303 | func nodeString(n ast.Node) string 1304 | 1305 | // mode returns a string describing the mode of an expression. 1306 | func mode(tv types.TypeAndValue) string 1307 | 1308 | 1309 | Given this input: 1310 | 1311 | 1312 | %include typeandvalue/main.go input - 1313 | 1314 | 1315 | the program prints: 1316 | 1317 | 1318 | %include typeandvalue/main.go output - 1319 | 1320 | 1321 | Notice that the identifiers for the built-ins `make` and 1322 | `print` have types that are specific to the particular calls in 1323 | which they appear. 1324 | Also notice `m["hello"]` has a 2-tuple type `(int, bool)` 1325 | and that it is assignable, but unlike the variable `m`, it is not 1326 | addressable. 1327 | 1328 | 1329 | 1330 | Download the example and vary the inputs and see what the program prints. 1331 | 1332 | 1333 | 1334 | Here's another example, adapted from the `govet` static checking tool. 1335 | It checks for accidental uses of a method value `x.f` when a 1336 | call `x.f()` was intended; 1337 | comparing a method `x.f` against nil is a common mistake. 1338 | 1339 | 1340 | %include nilfunc/main.go 1341 | 1342 | 1343 | Given this input, 1344 | 1345 | 1346 | %include nilfunc/main.go input - 1347 | 1348 | 1349 | the program reports these errors: 1350 | 1351 | 1352 | %include nilfunc/main.go output - 1353 | 1354 | # Selections 1355 | 1356 | 1357 | A _selection_ is an expression _`expr`_`.f` in which 1358 | `f` denotes either a struct field or a method. 1359 | A selection is resolved not by looking for a name in the lexical 1360 | environment, but by looking within a _type_. 1361 | The type checker ascertains the meaning of each selection in the 1362 | package---a surprisingly tricky business---and records it in the 1363 | `Selections` mapping of the `Info` struct, whose values are 1364 | of type `Selection`: 1365 | 1366 | 1367 | type Selection struct{ ... } 1368 | func (s *Selection) Kind() SelectionKind // = FieldVal | MethodVal | MethodExpr 1369 | func (s *Selection) Recv() Type 1370 | func (s *Selection) Obj() Object 1371 | func (s *Selection) Type() Type 1372 | func (s *Selection) Index() []int 1373 | func (s *Selection) Indirect() bool 1374 | 1375 | 1376 | The `Kind` method discriminates between the three (legal) kinds 1377 | of selections, as indicated by the comments below. 1378 | 1379 | 1380 | type T struct{Field int} 1381 | func (T) Method() {} 1382 | var v T 1383 | 1384 | // Kind Type 1385 | var _ = v.Field // FieldVal int 1386 | var _ = v.Method // MethodVal func() 1387 | var _ = T.Method // MethodExpr func(T) 1388 | 1389 | 1390 | Because of embedding, a selection may denote more than one field or 1391 | method, in which case it is ambiguous, and no `Selection` is 1392 | recorded for it. 1393 | 1394 | 1395 | 1396 | The `Obj` method returns the `Object` for the selected field 1397 | (`*Var`) or method (`*Func`). 1398 | Due to embedding, the object may belong to a different type than that 1399 | of the receiver expression _`expr`_. 1400 | The `Type` method returns the type of the selection. For a field 1401 | selection, this is the type of the field, but for method selections, 1402 | the result is a function type that is not the same as the type of the 1403 | method. 1404 | For a `MethodVal`, the receiver parameter is dropped, and 1405 | for a `MethodExpr`, the receiver parameter becomes a regular 1406 | parameter, as shown in the example above. 1407 | 1408 | 1409 | 1410 | The `Index` and `Indirect` methods report information about 1411 | implicit operations occurring during the selection that a compiler 1412 | would need to know about. 1413 | Because of embedding, a selection _`expr`_`.f` may be 1414 | shorthand for a sequence containing several implicit field selections, 1415 | _`expr`_`.d.e.f`, and `Index` reports the complete 1416 | sequence. 1417 | And because of automatic pointer dereferencing during struct field 1418 | accesses and method calls, a selection may imply one or more indirect 1419 | loads from memory; `Indirect` reports whether this occurs. 1420 | 1421 | 1422 | 1423 | Clients of the type checker can call `LookupFieldOrMethod` to 1424 | look up a name within a type, as if by a selection. 1425 | This function has an intimidating signature, but conceptually it 1426 | accepts just a `Type` and a name, and returns a `Selection`: 1427 | 1428 | 1429 | func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) \ 1430 | (obj Object, index []int, indirect bool) 1431 | 1432 | 1433 | The result is not actually a `Selection`, but it contains the 1434 | three main components of one: `Obj`, `Index`, 1435 | and `Indirect`. 1436 | 1437 | 1438 | 1439 | The `addressable` flag should be set if the receiver is a 1440 | _variable_ of type `T`, since in a method selection on a 1441 | variable, an implicit address-of operation (`&`) may occur. 1442 | The flag indicates whether the methods of type `*T` should be 1443 | considered during the lookup. 1444 | (You may wonder why this parameter is necessary. Couldn't clients 1445 | instead call `LookupFieldOrMethod` on the pointer type `*T` 1446 | if the receiver is a `T` variable? The answer is that if 1447 | `T` is an interface type, the type `*T` has no methods at 1448 | all.) 1449 | 1450 | 1451 | 1452 | The final two parameters of `LookupFieldOrMethod` are `(pkg 1453 | *Package, name string)`. 1454 | Together they specify the name of the field or method to look up. 1455 | This brings us to `Id`s. 1456 | 1457 | 1458 | 1459 | # Ids 1460 | 1461 | 1462 | `LookupFieldOrMethod`'s need for a `Package` parameter 1463 | is a subtle consequence of the 1464 | [_Uniqueness of identifiers_](https://golang.org/ref/spec#Uniqueness_of_identifiers) 1465 | section in the Go spec: "Two 1466 | identifiers are different if they are spelled differently, or if they 1467 | appear in different packages and are not exported." 1468 | In practical terms, this means that a type may have two methods 1469 | (or two fields, or one of each) both named `f` so long as those 1470 | methods are defined in different packages, as in this example: 1471 | 1472 | 1473 | package a 1474 | type A int 1475 | func (A) f() 1476 | 1477 | package b 1478 | type B int 1479 | func (B) f() 1480 | 1481 | package c 1482 | import ( "a"; "b" ) 1483 | type C struct{a.A; b.B} // C has two methods called f 1484 | 1485 | 1486 | The type `c.C` has two methods named `f`, but there is 1487 | no ambiguity because the two `f`s are distinct 1488 | identifiers---think of them as `fᵃ` and `fᵇ`. 1489 | For an exported method, this situation _would_ be ambiguous 1490 | because there is no distinction between `Fᵃ` and `Fᵇ`; there 1491 | is only `F`. 1492 | 1493 | 1494 | 1495 | Despite having two methods called `f`, neither of them can be 1496 | called from within package `c` because `c` has no way to 1497 | identify them. 1498 | Within `c`, `f` is the identifier `fᶜ`, and 1499 | type `C` has no method of that name. 1500 | But if we pass an instance of `C` to code in package `a` 1501 | and call its `f` method via an interface, `fᵃ` is called. 1502 | 1503 | 1504 | 1505 | The practical consequence for tool builders is that any time you need 1506 | to look up a field or method by name, or construct a map of fields and/or 1507 | methods keyed by name, it is not sufficient to use the object's name 1508 | as a key. 1509 | Instead, you must call the `Object.Id` method, which returns 1510 | a string that incorporates the object name, and for unexported 1511 | objects, the package path too. 1512 | There is also a standalone function `Id` that combines a name and 1513 | the package path in the same way: 1514 | 1515 | 1516 | func Id(pkg *Package, name string) string 1517 | 1518 | 1519 | This distinction applies to selections _`expr`_`.f`, but not 1520 | to lexical references `x` because for unexported identifiers, 1521 | declarations and references always appear in the same package. 1522 | 1523 | 1524 | 1525 | Fun fact: the `reflect.StructField` type records both the 1526 | `Name` and the `PkgPath` strings for the same reason. 1527 | The `FieldByName` methods of `reflect.Value` and 1528 | `reflect.Type` match field names without regard to the package. 1529 | If there is more than one match, they return an invalid value. 1530 | 1531 | 1532 | 1533 | 1534 | # Method Sets 1535 | 1536 | 1537 | The _method set_ of a type is the set of methods that can be 1538 | called on any value of that type. 1539 | (A variable of type `T` has access to all the methods of type 1540 | `*T` as well, due to the implicit address-of operation during 1541 | method calls, but those extra methods are not part of the method set 1542 | of `T`.) 1543 | 1544 | 1545 | 1546 | Clients can request the method set of a type `T` by calling 1547 | `NewMethodSet(T)`: 1548 | 1549 | 1550 | type MethodSet struct{ ... } 1551 | func NewMethodSet(T Type) *MethodSet 1552 | func (s *MethodSet) Len() int 1553 | func (s *MethodSet) At(i int) *Selection 1554 | func (s *MethodSet) Lookup(pkg *Package, name string) *Selection 1555 | 1556 | 1557 | The `Len` and `At` methods access a list of 1558 | `Selections`, all of kind `MethodVal`, ordered by `Id`. 1559 | The `Lookup` function allows lookup of a single method by 1560 | name (and package path, as explained in the previous section). 1561 | 1562 | 1563 | 1564 | `NewMethodSet` can be expensive, so for applications that compute 1565 | method sets repeatedly, `golang.org/x/tools/go/types/typeutil` 1566 | provides a `MethodSetCache` type that records previous results. 1567 | If you only need a single method, don't construct the 1568 | `MethodSet` at all; it's cheaper to use 1569 | `LookupFieldOrMethod`. 1570 | 1571 | 1572 | 1573 | The next program generates a boilerplate 1574 | declaration of a new concrete type that satisfies an existing 1575 | interface. 1576 | Here's an example: 1577 | 1578 | 1579 | %include skeleton/main.go output1 - 1580 | 1581 | 1582 | The three arguments are the package and the name of the existing 1583 | interface type, and the name of the new concrete type. 1584 | The `main` function (not shown) loads the specified package and 1585 | calls `PrintSkeleton` with the remaining two arguments: 1586 | 1587 | 1588 | %include skeleton/main.go 1589 | 1590 | 1591 | First, `PrintSkeleton` locates the package-level named interface 1592 | type, handling various error cases. 1593 | Then it chooses the name for the receiver of the new methods: the 1594 | first letter of the concrete type. 1595 | Finally, it iterates over the method set of the interface, printing 1596 | the corresponding concrete method declarations. 1597 | 1598 | 1599 | 1600 | There's a subtlety in the declaration of `sig`, which is the 1601 | string form of the method signature. 1602 | We could have obtained this string from `meth.Type().String()`, 1603 | but this would cause any named types within it to be formatted with 1604 | the complete package path, for instance 1605 | `net/http.ResponseWriter`, which is informative in diagnostics 1606 | but not legal Go syntax. 1607 | The `TypeString` function (explained in [Formatting Values](#formatting-values)) allows the 1608 | caller to control how packages are printed. 1609 | Passing `(*types.Package).Name` causes only the package name 1610 | `http` to be printed, not the complete path. 1611 | Here's another example that illustrates it: 1612 | 1613 | 1614 | %include skeleton/main.go output2 - 1615 | 1616 | 1617 | The following program inspects all pairs of package-level named types 1618 | in `pkg`, and reports the types that satisfy each interface type. 1619 | 1620 | 1621 | %include implements/main.go implements 1622 | 1623 | 1624 | Given this input, 1625 | 1626 | 1627 | %include implements/main.go input 1628 | 1629 | 1630 | the program prints: 1631 | 1632 | 1633 | %include implements/main.go output - 1634 | 1635 | 1636 | Notice that the method set of `B` does not include `g`, but 1637 | the method set of `*B` does. 1638 | That's why we needed the second assignability check, using the pointer 1639 | type `types.NewPointer(T)`. 1640 | 1641 | 1642 | 1643 | # Constants 1644 | 1645 | 1646 | A constant expression is one whose value is guaranteed to be computed at 1647 | compile time. 1648 | Constant expressions may appear in types, specifically as the length 1649 | of an array type such as `[16]byte`, so one of the jobs of the 1650 | type checker is to compute the value of each constant expression. 1651 | 1652 | 1653 | 1654 | As we saw in the `typeandvalue` example, the type checker records 1655 | the value of each constant expression like `"Hello, " + "world"`, 1656 | storing it in the `Value` field of the `TypeAndValue` struct. 1657 | Constants are represented using the `Value` interface from the 1658 | `go/constant` package. 1659 | 1660 | 1661 | package constant // go/constant 1662 | 1663 | type Value interface { 1664 | Kind() Kind 1665 | } 1666 | 1667 | type Kind int // one of Unknown, Bool, String, Int, Float, Complex 1668 | 1669 | 1670 | The interface has only one method, for discriminating the various 1671 | kinds of constants, but the package provides many functions for 1672 | inspecting a value of a known kind, 1673 | 1674 | 1675 | // Accessors 1676 | func BoolVal(x Value) bool 1677 | func Float32Val(x Value) (float32, bool) 1678 | func Float64Val(x Value) (float64, bool) 1679 | func Int64Val(x Value) (int64, bool) 1680 | func StringVal(x Value) string 1681 | func Uint64Val(x Value) (uint64, bool) 1682 | func Bytes(x Value) []byte 1683 | func BitLen(x Value) int 1684 | func Sign(x Value) int 1685 | 1686 | 1687 | for performing arithmetic on values, 1688 | 1689 | 1690 | // Operations 1691 | func Compare(x Value, op token.Token, y Value) bool 1692 | func UnaryOp(op token.Token, y Value, prec uint) Value 1693 | func BinaryOp(x Value, op token.Token, y Value) Value 1694 | func Shift(x Value, op token.Token, s uint) Value 1695 | func Denom(x Value) Value 1696 | func Num(x Value) Value 1697 | func Real(x Value) Value 1698 | func Imag(x Value) Value 1699 | 1700 | 1701 | and for constructing new values: 1702 | 1703 | 1704 | // Constructors 1705 | func MakeBool(b bool) Value 1706 | func MakeFloat64(x float64) Value 1707 | func MakeFromBytes(bytes []byte) Value 1708 | func MakeFromLiteral(lit string, tok token.Token, prec uint) Value 1709 | func MakeImag(x Value) Value 1710 | func MakeInt64(x int64) Value 1711 | func MakeString(s string) Value 1712 | func MakeUint64(x uint64) Value 1713 | func MakeUnknown() Value 1714 | 1715 | 1716 | All numeric `Value`s, whether integer or floating-point, signed or 1717 | unsigned, or real or complex, are represented more precisely than 1718 | ordinary Go types like `int64` and `float64`. 1719 | Internally, the `go/constant` package uses multi-precision data types 1720 | like `Int`, `Rat`, and `Float` from the `math/big` package so that 1721 | `Values` and their arithmetic operations are accurate to at least 256 1722 | bits, as required by the Go specification. 1723 | 1724 | 1725 | 1726 | 1727 | 1728 | # Size and Alignment 1729 | 1730 | 1731 | Because the calls `unsafe.Sizeof(v)`, `unsafe.Alignof(v)`, 1732 | and `unsafe.Offsetof(v.f)` are all constant expressions, the type 1733 | checker must be able to compute the memory layout of any value 1734 | `v`. 1735 | 1736 | 1737 | 1738 | By default, the type checker uses the same layout algorithm as the Go 1739 | 1.5 `gc` compiler targeting `amd64`. 1740 | Clients can configure the type checker to use a different algorithm by 1741 | providing an instance of the `types.Sizes` interface in the 1742 | `types.Config` struct: 1743 | 1744 | 1745 | package types 1746 | 1747 | type Sizes interface { 1748 | Alignof(T Type) int64 1749 | Offsetsof(fields []*Var) []int64 1750 | Sizeof(T Type) int64 1751 | } 1752 | 1753 | 1754 | 1755 | For common changes, like reducing the word size to 32 bits, clients 1756 | can use an instance of `StdSizes`: 1757 | 1758 | 1759 | type StdSizes struct { 1760 | WordSize int64 1761 | MaxAlign int64 1762 | } 1763 | 1764 | 1765 | This type has two basic size and alignment parameters from which it 1766 | derives all the other values using common assumptions. 1767 | For example, pointers, functions, maps, and channels fit in one word, 1768 | strings and interfaces require two words, and slices need three. 1769 | The default behaviour is equivalent to `StdSizes{8, 8}`. 1770 | For more esoteric layout changes, you'll need to write a new 1771 | implementation of the `Sizes` interface. 1772 | 1773 | 1774 | 1775 | The `hugeparam` program below prints all function parameters and 1776 | results whose size exceeds a threshold. 1777 | By default, the threshold is 48 bytes, but you can set it via the 1778 | `-bytes` command-line flag. 1779 | Such a tool could help identify inefficient parameter passing in your 1780 | programs. 1781 | 1782 | 1783 | %include hugeparam/main.go 1784 | 1785 | 1786 | As before, `Inspect` applies a function to every node in the AST. 1787 | The function cares about two kinds of nodes: declarations of named 1788 | functions and methods (`*ast.FuncDecl`) and function literals 1789 | (`*ast.FuncLit`). 1790 | Observe the two cases' different logic to obtain the type of each 1791 | function. 1792 | 1793 | 1794 | 1795 | Here's a typical invocation on the standard `encoding/xml` package. 1796 | It reports a number of places where the 7-word 1797 | [`StartElement` type](https://pkg.go.dev/encoding/xml#StartElement) 1798 | is copied. 1799 | 1800 | 1801 | %include hugeparam/main.go output - 1802 | 1803 | # Imports 1804 | 1805 | 1806 | The type checker's `Check` function processes a slice of parsed 1807 | files (`[]*ast.File`) that make up one package. 1808 | When the type checker encounters an import declaration, it needs the 1809 | type information for the objects in the imported package. 1810 | It gets it by calling the `Import` method of the `Importer` 1811 | interface shown below, an instance of which must be provided by the 1812 | `Config`. 1813 | This separation of concerns relieves the type checker from having to 1814 | know any of the details of Go workspace organization, `GOPATH`, 1815 | compiler file formats, and so on. 1816 | 1817 | 1818 | type Importer interface { 1819 | Import(path string) (*Package, error) 1820 | } 1821 | 1822 | 1823 | Most of our examples used the simplest `Importer` implementation, 1824 | `importer.Default()`, provided by the `go/importer` package. 1825 | This importer looks in `$GOROOT` and `$GOPATH` for `.a` 1826 | files written by the compiler (`gc` or `gccgo`) 1827 | that was used to build the program. 1828 | In addition to object code, these files contain _export data_, 1829 | that is, a description of all the objects declared by the package, and 1830 | also of any objects from other packages that were referred to indirectly. 1831 | Because export data includes information about dependencies, the type 1832 | checker need load at most one file per import, instead of one per 1833 | transitive dependency. 1834 | 1835 | 1836 | 1837 | Compiler export data is compact and efficient to locate, load, and 1838 | parse, but it has several shortcomings. 1839 | First, it does not contain position information for imported 1840 | objects, reducing the quality of certain diagnostic messages. 1841 | Second, it does not contain complete syntax trees nor semantic information 1842 | about the contents of function bodies, so it is not suitable for 1843 | interprocedural analyses. 1844 | Third, compiler object data may be stale. Nothing detects or ensures 1845 | that the object files are more recent than the source files from which 1846 | they were derived. 1847 | Generally, object data for standard packages is likely to be 1848 | up-to-date, but for user packages, it depends on how recently the user 1849 | ran a `go install` or `go build -i` command. 1850 | 1851 | 1852 | 1853 | The [`golang.org/tools/x/go/loader` package](https://pkg.go.dev/golang.org/x/tools/go/loader) 1854 | provides an alternative `Importer` that addresses 1855 | some of these problems. 1856 | It loads a complete program from source, performing 1857 | [`cgo`](https://golang.org/cmd/cgo/cgo) preprocessing if 1858 | necessary, followed by parsing and type-checking. 1859 | It loads independent packages in parallel to hide I/O latency, and 1860 | detects and reports import cycles. 1861 | For each package, it provides the `types.Package` containing the 1862 | package's lexical environment, the list of `ast.File` syntax 1863 | trees for each file in the package, the `types.Info` containing 1864 | type information for each syntax node, and a list of type errors 1865 | associated with that package. 1866 | (Please be aware that the `go/loader` package's API is likely to 1867 | change before it finally stabilizes.) 1868 | 1869 | 1870 | 1871 | The `doc` program below demonstrates a simple use of the loader. 1872 | It is a rudimentary implementation of `go doc` that prints the type, 1873 | methods, and documentation of the package-level object specified on 1874 | the command line. 1875 | Here's an example: 1876 | 1877 | 1878 | %include doc/main.go output - 1879 | 1880 | 1881 | Observe that it prints the correct location of each method 1882 | declaration, even though, due to embedding, some of 1883 | `http.File`'s methods were declared in another package. 1884 | Here's the first part of the program, showing how to load an entire 1885 | program starting from the single package, `pkgpath`: 1886 | 1887 | 1888 | %include doc/main.go part1 1889 | 1890 | 1891 | Notice that we instructed the parser to retain comments during parsing. 1892 | The rest of the program prints the output: 1893 | 1894 | 1895 | %include doc/main.go part2 1896 | 1897 | 1898 | We used `IntuitiveMethodSet` to compute the method set, instead 1899 | of `NewMethodSet`. 1900 | The result of this convenience function, which is intended for use in 1901 | user interfaces, includes methods of `*T` as well as those of 1902 | `T`, since that matches most users' intuition about the method 1903 | set of a type. 1904 | (Our example, `http.File`, didn't illustrate the difference, but try 1905 | running it on a type with both value and pointer methods.) 1906 | 1907 | 1908 | 1909 | Also notice `PathEnclosingInterval`, which finds the set of AST 1910 | nodes that enclose a particular point, in this case, the object's 1911 | declaring identifier. 1912 | By walking up with path, we find the enclosing declaration, to which 1913 | the documentation is attached. 1914 | 1915 | 1916 | 1917 | # Formatting support 1918 | 1919 | 1920 | All types that satisfy `Type` or `Object` define a 1921 | `String` method that formats the type or object in a readable 1922 | notation. `Selection` also provides a `String` method. 1923 | All package-level objects within these data structures are 1924 | printed with the complete package path, as in these examples: 1925 | 1926 | 1927 | []encoding/json.Marshaler // a *Slice type 1928 | encoding/json.Marshal // a *Func object 1929 | (*encoding/json.Encoder).Encode // a *Func object (method) 1930 | func (enc *encoding/json.Encoder) Encode(v interface{}) error // a method *Signature 1931 | func NewEncoder(w io.Writer) *encoding/json.Encoder // a function *Signature 1932 | 1933 | 1934 | This notation is unambiguous, but it is not legal Go syntax. 1935 | Also, package paths may be long, and the same package path may appear 1936 | many times in a single string, for instance, when formatting a 1937 | function of several parameters. 1938 | Because these strings often form part of a tool's user interface---as 1939 | with the diagnostic messages of `hugeparam` or the code generated 1940 | by `skeleton`---many clients want more control over the 1941 | formatting of package names. 1942 | 1943 | 1944 | 1945 | The `go/types` package provides these alternatives to the 1946 | `String` methods: 1947 | 1948 | 1949 | func ObjectString(obj Object, qf Qualifier) string 1950 | func TypeString(typ Type, qf Qualifier) string 1951 | func SelectionString(s *Selection, qf Qualifier) string 1952 | 1953 | type Qualifier func(*Package) string 1954 | 1955 | 1956 | The `TypeString`, `ObjectString`, and `SelectionString` 1957 | functions are like the `String` methods of the respective types, 1958 | but they accept an additional argument, a `Qualifier`. 1959 | 1960 | 1961 | 1962 | A `Qualifier` is a client-provided function that determines how a 1963 | package name is rendered as a string. 1964 | If it is nil, the default behavior is to print the package's 1965 | path, just like the `String` methods do. 1966 | If a caller passes `(*Package).Name` as the qualifier, that is, a 1967 | function that accepts a package and returns its `Name`, then 1968 | objects are qualified only by the package name. 1969 | The above examples would look like this: 1970 | 1971 | 1972 | []json.Marshaler 1973 | json.Marshal 1974 | (*json.Encoder).Encode 1975 | func (enc *json.Encoder) Encode(v interface{}) error 1976 | func NewEncoder(w io.Writer) *json.Encoder 1977 | 1978 | 1979 | Often when a tool prints some output, it is implicitly in the 1980 | context of a particular package, perhaps one specified by the 1981 | command line or HTTP request. 1982 | In that case, it is more natural to omit the package qualification 1983 | altogether for objects belonging to that package, but to qualify all 1984 | other objects by their package's path. 1985 | That's what the `RelativeTo(pkg)` qualifier does: 1986 | 1987 | 1988 | func RelativeTo(pkg *Package) Qualifier 1989 | 1990 | 1991 | The examples below show how `json.NewEncoder` would be printed 1992 | using three qualifiers, each relative to a different package: 1993 | 1994 | 1995 | // RelativeTo "encoding/json": 1996 | func NewEncoder(w io.Writer) *Encoder 1997 | 1998 | // RelativeTo "io": 1999 | func NewEncoder(w Writer) *encoding/json.Encoder 2000 | 2001 | // RelativeTo any other package: 2002 | func NewEncoder(w io.Writer) *encoding/json.Encoder 2003 | 2004 | 2005 | Another qualifier that may be relevant to refactoring tools (but is 2006 | not currently provided by the type checker) is one that renders each 2007 | package name using the locally appropriate name within a given source 2008 | file. 2009 | Its behavior would depend on the set of import declarations, including 2010 | renaming imports, within that source file. 2011 | 2012 | 2013 | 2014 | # Getting from A to B 2015 | 2016 | 2017 | The type checker and its related packages represent many aspects of a 2018 | Go program in many different ways, and analysis tools must often map 2019 | between them. 2020 | For instance, a named entity may be identified by its `Object`; 2021 | by its declaring identifier (`ast.Ident`) or by any referring 2022 | identifier; by its declaring `ast.Node`; by the position 2023 | (`token.Pos`) of any those nodes; or by the filename and 2024 | line/column number (or byte offset) of those `token.Pos` values. 2025 | 2026 | 2027 | 2028 | In this section, we'll list solutions to a number of common problems 2029 | of the form "I have an A; I need the corresponding B". 2030 | 2031 | 2032 | 2033 | To map **from a `token.Pos` to an `ast.Node`**, call the 2034 | helper function 2035 | [`astutil.PathEnclosingInterval`](https://pkg.go.dev/golang.org/x/tools/go/ast/astutil#PathEnclosingInterval). 2036 | It returns the enclosing `ast.Node`, and all its ancestors up to 2037 | the root of the file. 2038 | You must know which file `*ast.File` the `token.Pos` belongs to. 2039 | Alternatively, you can search an entire program loaded by the 2040 | `loader` package, using 2041 | [`(*loader.Program).PathEnclosingInterval`](https://pkg.go.dev/golang.org/x/tools/go/loader#Program.PathEnclosingInterval). 2042 | 2043 | 2044 | 2045 | To map **from an `Object` to its declaring syntax**, call 2046 | `Pos` to get its position, then use `PathEnclosingInterval` as before. 2047 | This approach is suitable for a one-off query. For repeated use, it 2048 | may be more efficient to visit the syntax tree and construct the 2049 | mapping between declarations and objects. 2050 | 2051 | 2052 | 2053 | To map **from an `ast.Ident` to the `Object`** it refers to (or 2054 | declares), consult the `Uses` or `Defs` map for the 2055 | package, as shown in [Identifier Resolution](#identifier-resolution). 2056 | 2057 | 2058 | 2059 | To map **from an `Object` to its documentation**, find the 2060 | object's declaration, and look at the attached `Doc` field. 2061 | You must have set the parser's `ParseComments` flag. 2062 | See the `doc` example in [Imports](#imports). 2063 | -------------------------------------------------------------------------------- /gotypes/hello/hello.go: -------------------------------------------------------------------------------- 1 | // !+ 2 | package main 3 | 4 | import "fmt" 5 | 6 | func main() { 7 | fmt.Println("Hello, 世界") 8 | } 9 | 10 | //!- 11 | -------------------------------------------------------------------------------- /gotypes/hugeparam/main.go: -------------------------------------------------------------------------------- 1 | // The hugeparam command identifies by-value parameters that are larger than n bytes. 2 | // 3 | // Example: 4 | // 5 | // $ ./hugeparams encoding/xml 6 | package main 7 | 8 | import ( 9 | "flag" 10 | "fmt" 11 | "go/ast" 12 | "go/token" 13 | "go/types" 14 | "log" 15 | 16 | "golang.org/x/tools/go/loader" 17 | ) 18 | 19 | // !+ 20 | var bytesFlag = flag.Int("bytes", 48, "maximum parameter size in bytes") 21 | 22 | var sizeof = (&types.StdSizes{8, 8}).Sizeof // the sizeof function 23 | 24 | func PrintHugeParams(fset *token.FileSet, info *types.Info, files []*ast.File) { 25 | checkTuple := func(descr string, tuple *types.Tuple) { 26 | for i := 0; i < tuple.Len(); i++ { 27 | v := tuple.At(i) 28 | if sz := sizeof(v.Type()); sz > int64(*bytesFlag) { 29 | fmt.Printf("%s: %q %s: %s = %d bytes\n", 30 | fset.Position(v.Pos()), 31 | v.Name(), descr, v.Type(), sz) 32 | } 33 | } 34 | } 35 | checkSig := func(sig *types.Signature) { 36 | checkTuple("parameter", sig.Params()) 37 | checkTuple("result", sig.Results()) 38 | } 39 | for _, file := range files { 40 | ast.Inspect(file, func(n ast.Node) bool { 41 | switch n := n.(type) { 42 | case *ast.FuncDecl: 43 | checkSig(info.Defs[n.Name].Type().(*types.Signature)) 44 | case *ast.FuncLit: 45 | checkSig(info.Types[n.Type].Type.(*types.Signature)) 46 | } 47 | return true 48 | }) 49 | } 50 | } 51 | 52 | //!- 53 | 54 | func main() { 55 | flag.Parse() 56 | 57 | // The loader loads a complete Go program from source code. 58 | var conf loader.Config 59 | _, err := conf.FromArgs(flag.Args(), false) 60 | if err != nil { 61 | log.Fatal(err) // command syntax error 62 | } 63 | lprog, err := conf.Load() 64 | if err != nil { 65 | log.Fatal(err) // load error 66 | } 67 | 68 | for _, info := range lprog.InitialPackages() { 69 | PrintHugeParams(lprog.Fset, &info.Info, info.Files) 70 | } 71 | } 72 | 73 | /* 74 | //!+output 75 | % ./hugeparam encoding/xml 76 | /go/src/encoding/xml/marshal.go:167:50: "start" parameter: encoding/xml.StartElement = 56 bytes 77 | /go/src/encoding/xml/marshal.go:734:97: "" result: encoding/xml.StartElement = 56 bytes 78 | /go/src/encoding/xml/marshal.go:761:51: "start" parameter: encoding/xml.StartElement = 56 bytes 79 | /go/src/encoding/xml/marshal.go:781:68: "start" parameter: encoding/xml.StartElement = 56 bytes 80 | /go/src/encoding/xml/xml.go:72:30: "" result: encoding/xml.StartElement = 56 bytes 81 | //!-output 82 | */ 83 | -------------------------------------------------------------------------------- /gotypes/implements/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 | // !+input 14 | const input = `package main 15 | 16 | type A struct{} 17 | func (*A) f() 18 | 19 | type B int 20 | func (B) f() 21 | func (*B) g() 22 | 23 | type I interface { f() } 24 | type J interface { g() } 25 | ` 26 | 27 | //!-input 28 | 29 | func main() { 30 | // Parse one file. 31 | fset := token.NewFileSet() 32 | f, err := parser.ParseFile(fset, "input.go", input, 0) 33 | if err != nil { 34 | log.Fatal(err) // parse error 35 | } 36 | conf := types.Config{Importer: importer.Default()} 37 | pkg, err := conf.Check("hello", fset, []*ast.File{f}, nil) 38 | if err != nil { 39 | log.Fatal(err) // type error 40 | } 41 | 42 | //!+implements 43 | // Find all named types at package level. 44 | var allNamed []*types.Named 45 | for _, name := range pkg.Scope().Names() { 46 | if obj, ok := pkg.Scope().Lookup(name).(*types.TypeName); ok { 47 | allNamed = append(allNamed, obj.Type().(*types.Named)) 48 | } 49 | } 50 | 51 | // Test assignability of all distinct pairs of 52 | // named types (T, U) where U is an interface. 53 | for _, T := range allNamed { 54 | for _, U := range allNamed { 55 | if T == U || !types.IsInterface(U) { 56 | continue 57 | } 58 | if types.AssignableTo(T, U) { 59 | fmt.Printf("%s satisfies %s\n", T, U) 60 | } else if !types.IsInterface(T) && 61 | types.AssignableTo(types.NewPointer(T), U) { 62 | fmt.Printf("%s satisfies %s\n", types.NewPointer(T), U) 63 | } 64 | } 65 | } 66 | //!-implements 67 | } 68 | 69 | /* 70 | //!+output 71 | $ go build golang.org/x/example/gotypes/implements 72 | $ ./implements 73 | *hello.A satisfies hello.I 74 | hello.B satisfies hello.I 75 | *hello.B satisfies hello.J 76 | //!-output 77 | */ 78 | -------------------------------------------------------------------------------- /gotypes/lookup/lookup.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 | "strings" 12 | ) 13 | 14 | // !+input 15 | const hello = ` 16 | package main 17 | 18 | import "fmt" 19 | 20 | // append 21 | func main() { 22 | // fmt 23 | fmt.Println("Hello, world") 24 | // main 25 | main, x := 1, 2 26 | // main 27 | print(main, x) 28 | // x 29 | } 30 | // x 31 | ` 32 | 33 | //!-input 34 | 35 | // !+main 36 | func main() { 37 | fset := token.NewFileSet() 38 | f, err := parser.ParseFile(fset, "hello.go", hello, parser.ParseComments) 39 | if err != nil { 40 | log.Fatal(err) // parse error 41 | } 42 | 43 | conf := types.Config{Importer: importer.Default()} 44 | pkg, err := conf.Check("cmd/hello", fset, []*ast.File{f}, nil) 45 | if err != nil { 46 | log.Fatal(err) // type error 47 | } 48 | 49 | // Each comment contains a name. 50 | // Look up that name in the innermost scope enclosing the comment. 51 | for _, comment := range f.Comments { 52 | pos := comment.Pos() 53 | name := strings.TrimSpace(comment.Text()) 54 | fmt.Printf("At %s,\t%q = ", fset.Position(pos), name) 55 | inner := pkg.Scope().Innermost(pos) 56 | if _, obj := inner.LookupParent(name, pos); obj != nil { 57 | fmt.Println(obj) 58 | } else { 59 | fmt.Println("not found") 60 | } 61 | } 62 | } 63 | 64 | //!-main 65 | 66 | /* 67 | //!+output 68 | $ go build golang.org/x/example/gotypes/lookup 69 | $ ./lookup 70 | At hello.go:6:1, "append" = builtin append 71 | At hello.go:8:9, "fmt" = package fmt 72 | At hello.go:10:9, "main" = func cmd/hello.main() 73 | At hello.go:12:9, "main" = var main int 74 | At hello.go:14:9, "x" = var x int 75 | At hello.go:16:1, "x" = not found 76 | //!-output 77 | */ 78 | -------------------------------------------------------------------------------- /gotypes/nilfunc/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 | // !+input 14 | const input = `package main 15 | 16 | import "bytes" 17 | 18 | func main() { 19 | var buf bytes.Buffer 20 | if buf.Bytes == nil && bytes.Repeat != nil && main == nil { 21 | // ... 22 | } 23 | } 24 | ` 25 | 26 | //!-input 27 | 28 | var fset = token.NewFileSet() 29 | 30 | func main() { 31 | f, err := parser.ParseFile(fset, "input.go", input, 0) 32 | if err != nil { 33 | log.Fatal(err) // parse error 34 | } 35 | conf := types.Config{Importer: importer.Default()} 36 | info := &types.Info{ 37 | Defs: make(map[*ast.Ident]types.Object), 38 | Uses: make(map[*ast.Ident]types.Object), 39 | Types: make(map[ast.Expr]types.TypeAndValue), 40 | } 41 | if _, err = conf.Check("cmd/hello", fset, []*ast.File{f}, info); err != nil { 42 | log.Fatal(err) // type error 43 | } 44 | 45 | ast.Inspect(f, func(n ast.Node) bool { 46 | if n != nil { 47 | CheckNilFuncComparison(info, n) 48 | } 49 | return true 50 | }) 51 | } 52 | 53 | // !+ 54 | // CheckNilFuncComparison reports unintended comparisons 55 | // of functions against nil, e.g., "if x.Method == nil {". 56 | func CheckNilFuncComparison(info *types.Info, n ast.Node) { 57 | e, ok := n.(*ast.BinaryExpr) 58 | if !ok { 59 | return // not a binary operation 60 | } 61 | if e.Op != token.EQL && e.Op != token.NEQ { 62 | return // not a comparison 63 | } 64 | 65 | // If this is a comparison against nil, find the other operand. 66 | var other ast.Expr 67 | if info.Types[e.X].IsNil() { 68 | other = e.Y 69 | } else if info.Types[e.Y].IsNil() { 70 | other = e.X 71 | } else { 72 | return // not a comparison against nil 73 | } 74 | 75 | // Find the object. 76 | var obj types.Object 77 | switch v := other.(type) { 78 | case *ast.Ident: 79 | obj = info.Uses[v] 80 | case *ast.SelectorExpr: 81 | obj = info.Uses[v.Sel] 82 | default: 83 | return // not an identifier or selection 84 | } 85 | 86 | if _, ok := obj.(*types.Func); !ok { 87 | return // not a function or method 88 | } 89 | 90 | fmt.Printf("%s: comparison of function %v %v nil is always %v\n", 91 | fset.Position(e.Pos()), obj.Name(), e.Op, e.Op == token.NEQ) 92 | } 93 | 94 | //!- 95 | 96 | /* 97 | //!+output 98 | $ go build golang.org/x/example/gotypes/nilfunc 99 | $ ./nilfunc 100 | input.go:7:5: comparison of function Bytes == nil is always false 101 | input.go:7:25: comparison of function Repeat != nil is always true 102 | input.go:7:48: comparison of function main == nil is always false 103 | //!-output 104 | */ 105 | -------------------------------------------------------------------------------- /gotypes/pkginfo/main.go: -------------------------------------------------------------------------------- 1 | // !+ 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "go/ast" 7 | "go/importer" 8 | "go/parser" 9 | "go/token" 10 | "go/types" 11 | "log" 12 | ) 13 | 14 | const hello = `package main 15 | 16 | import "fmt" 17 | 18 | func main() { 19 | fmt.Println("Hello, world") 20 | }` 21 | 22 | func main() { 23 | fset := token.NewFileSet() 24 | 25 | // Parse the input string, []byte, or io.Reader, 26 | // recording position information in fset. 27 | // ParseFile returns an *ast.File, a syntax tree. 28 | f, err := parser.ParseFile(fset, "hello.go", hello, 0) 29 | if err != nil { 30 | log.Fatal(err) // parse error 31 | } 32 | 33 | // A Config controls various options of the type checker. 34 | // The defaults work fine except for one setting: 35 | // we must specify how to deal with imports. 36 | conf := types.Config{Importer: importer.Default()} 37 | 38 | // Type-check the package containing only file f. 39 | // Check returns a *types.Package. 40 | pkg, err := conf.Check("cmd/hello", fset, []*ast.File{f}, nil) 41 | if err != nil { 42 | log.Fatal(err) // type error 43 | } 44 | 45 | fmt.Printf("Package %q\n", pkg.Path()) 46 | fmt.Printf("Name: %s\n", pkg.Name()) 47 | fmt.Printf("Imports: %s\n", pkg.Imports()) 48 | fmt.Printf("Scope: %s\n", pkg.Scope()) 49 | } 50 | 51 | //!- 52 | 53 | /* 54 | //!+output 55 | $ go build golang.org/x/example/gotypes/pkginfo 56 | $ ./pkginfo 57 | Package "cmd/hello" 58 | Name: main 59 | Imports: [package fmt ("fmt")] 60 | Scope: package "cmd/hello" scope 0x820533590 { 61 | . func cmd/hello.main() 62 | } 63 | //!-output 64 | */ 65 | -------------------------------------------------------------------------------- /gotypes/skeleton/main.go: -------------------------------------------------------------------------------- 1 | // The skeleton command prints the boilerplate for a concrete type 2 | // that implements the specified interface type. 3 | // 4 | // Example: 5 | // 6 | // $ ./skeleton io ReadWriteCloser buffer 7 | // // *buffer implements io.ReadWriteCloser. 8 | // type buffer struct{ /* ... */ } 9 | // func (b *buffer) Close() error { panic("unimplemented") } 10 | // func (b *buffer) Read(p []byte) (n int, err error) { panic("unimplemented") } 11 | // func (b *buffer) Write(p []byte) (n int, err error) { panic("unimplemented") } 12 | package main 13 | 14 | import ( 15 | "fmt" 16 | "go/types" 17 | "log" 18 | "os" 19 | "strings" 20 | "unicode" 21 | "unicode/utf8" 22 | 23 | "golang.org/x/tools/go/loader" 24 | ) 25 | 26 | const usage = "Usage: skeleton " 27 | 28 | // !+ 29 | func PrintSkeleton(pkg *types.Package, ifacename, concname string) error { 30 | obj := pkg.Scope().Lookup(ifacename) 31 | if obj == nil { 32 | return fmt.Errorf("%s.%s not found", pkg.Path(), ifacename) 33 | } 34 | if _, ok := obj.(*types.TypeName); !ok { 35 | return fmt.Errorf("%v is not a named type", obj) 36 | } 37 | iface, ok := obj.Type().Underlying().(*types.Interface) 38 | if !ok { 39 | return fmt.Errorf("type %v is a %T, not an interface", 40 | obj, obj.Type().Underlying()) 41 | } 42 | // Use first letter of type name as receiver parameter. 43 | if !isValidIdentifier(concname) { 44 | return fmt.Errorf("invalid concrete type name: %q", concname) 45 | } 46 | r, _ := utf8.DecodeRuneInString(concname) 47 | 48 | fmt.Printf("// *%s implements %s.%s.\n", concname, pkg.Path(), ifacename) 49 | fmt.Printf("type %s struct{}\n", concname) 50 | mset := types.NewMethodSet(iface) 51 | for i := 0; i < mset.Len(); i++ { 52 | meth := mset.At(i).Obj() 53 | sig := types.TypeString(meth.Type(), (*types.Package).Name) 54 | fmt.Printf("func (%c *%s) %s%s {\n\tpanic(\"unimplemented\")\n}\n", 55 | r, concname, meth.Name(), 56 | strings.TrimPrefix(sig, "func")) 57 | } 58 | return nil 59 | } 60 | 61 | //!- 62 | 63 | func isValidIdentifier(id string) bool { 64 | for i, r := range id { 65 | if !unicode.IsLetter(r) && 66 | !(i > 0 && unicode.IsDigit(r)) { 67 | return false 68 | } 69 | } 70 | return id != "" 71 | } 72 | 73 | func main() { 74 | if len(os.Args) != 4 { 75 | log.Fatal(usage) 76 | } 77 | pkgpath, ifacename, concname := os.Args[1], os.Args[2], os.Args[3] 78 | 79 | // The loader loads a complete Go program from source code. 80 | var conf loader.Config 81 | conf.Import(pkgpath) 82 | lprog, err := conf.Load() 83 | if err != nil { 84 | log.Fatal(err) // load error 85 | } 86 | pkg := lprog.Package(pkgpath).Pkg 87 | if err := PrintSkeleton(pkg, ifacename, concname); err != nil { 88 | log.Fatal(err) 89 | } 90 | } 91 | 92 | /* 93 | //!+output1 94 | $ ./skeleton io ReadWriteCloser buffer 95 | // *buffer implements io.ReadWriteCloser. 96 | type buffer struct{} 97 | func (b *buffer) Close() error { 98 | panic("unimplemented") 99 | } 100 | func (b *buffer) Read(p []byte) (n int, err error) { 101 | panic("unimplemented") 102 | } 103 | func (b *buffer) Write(p []byte) (n int, err error) { 104 | panic("unimplemented") 105 | } 106 | //!-output1 107 | 108 | //!+output2 109 | $ ./skeleton net/http Handler myHandler 110 | // *myHandler implements net/http.Handler. 111 | type myHandler struct{} 112 | func (m *myHandler) ServeHTTP(http.ResponseWriter, *http.Request) { 113 | panic("unimplemented") 114 | } 115 | //!-output2 116 | */ 117 | -------------------------------------------------------------------------------- /gotypes/typeandvalue/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "go/ast" 7 | "go/format" 8 | "go/importer" 9 | "go/parser" 10 | "go/token" 11 | "go/types" 12 | "log" 13 | ) 14 | 15 | // !+input 16 | const input = ` 17 | package main 18 | 19 | var m = make(map[string]int) 20 | 21 | func main() { 22 | v, ok := m["hello, " + "world"] 23 | print(rune(v), ok) 24 | } 25 | ` 26 | 27 | //!-input 28 | 29 | var fset = token.NewFileSet() 30 | 31 | func main() { 32 | f, err := parser.ParseFile(fset, "hello.go", input, 0) 33 | if err != nil { 34 | log.Fatal(err) // parse error 35 | } 36 | 37 | conf := types.Config{Importer: importer.Default()} 38 | info := &types.Info{Types: make(map[ast.Expr]types.TypeAndValue)} 39 | if _, err := conf.Check("cmd/hello", fset, []*ast.File{f}, info); err != nil { 40 | log.Fatal(err) // type error 41 | } 42 | 43 | //!+inspect 44 | // f is a parsed, type-checked *ast.File. 45 | ast.Inspect(f, func(n ast.Node) bool { 46 | if expr, ok := n.(ast.Expr); ok { 47 | if tv, ok := info.Types[expr]; ok { 48 | fmt.Printf("%-24s\tmode: %s\n", nodeString(expr), mode(tv)) 49 | fmt.Printf("\t\t\t\ttype: %v\n", tv.Type) 50 | if tv.Value != nil { 51 | fmt.Printf("\t\t\t\tvalue: %v\n", tv.Value) 52 | } 53 | } 54 | } 55 | return true 56 | }) 57 | //!-inspect 58 | } 59 | 60 | // nodeString formats a syntax tree in the style of gofmt. 61 | func nodeString(n ast.Node) string { 62 | var buf bytes.Buffer 63 | format.Node(&buf, fset, n) 64 | return buf.String() 65 | } 66 | 67 | // mode returns a string describing the mode of an expression. 68 | func mode(tv types.TypeAndValue) string { 69 | s := "" 70 | if tv.IsVoid() { 71 | s += ",void" 72 | } 73 | if tv.IsType() { 74 | s += ",type" 75 | } 76 | if tv.IsBuiltin() { 77 | s += ",builtin" 78 | } 79 | if tv.IsValue() { 80 | s += ",value" 81 | } 82 | if tv.IsNil() { 83 | s += ",nil" 84 | } 85 | if tv.Addressable() { 86 | s += ",addressable" 87 | } 88 | if tv.Assignable() { 89 | s += ",assignable" 90 | } 91 | if tv.HasOk() { 92 | s += ",ok" 93 | } 94 | return s[1:] 95 | } 96 | 97 | /* 98 | //!+output 99 | $ go build golang.org/x/example/gotypes/typeandvalue 100 | $ ./typeandvalue 101 | make(map[string]int) mode: value 102 | type: map[string]int 103 | make mode: builtin 104 | type: func(map[string]int) map[string]int 105 | map[string]int mode: type 106 | type: map[string]int 107 | string mode: type 108 | type: string 109 | int mode: type 110 | type: int 111 | m["hello, "+"world"] mode: value,assignable,ok 112 | type: (int, bool) 113 | m mode: value,addressable,assignable 114 | type: map[string]int 115 | "hello, " + "world" mode: value 116 | type: string 117 | value: "hello, world" 118 | "hello, " mode: value 119 | type: untyped string 120 | value: "hello, " 121 | "world" mode: value 122 | type: untyped string 123 | value: "world" 124 | print(rune(v), ok) mode: void 125 | type: () 126 | print mode: builtin 127 | type: func(rune, bool) 128 | rune(v) mode: value 129 | type: rune 130 | rune mode: type 131 | type: rune 132 | ...more not shown... 133 | //!-output 134 | */ 135 | -------------------------------------------------------------------------------- /gotypes/weave.go: -------------------------------------------------------------------------------- 1 | // The weave command is a simple preprocessor for markdown files. 2 | // It builds a table of contents and processes %include directives. 3 | // 4 | // Example usage: 5 | // 6 | // $ go run weave.go go-types.md > README.md 7 | package main 8 | 9 | import ( 10 | "bufio" 11 | "bytes" 12 | "fmt" 13 | "log" 14 | "os" 15 | "path/filepath" 16 | "regexp" 17 | "strings" 18 | ) 19 | 20 | func main() { 21 | log.SetFlags(0) 22 | log.SetPrefix("weave: ") 23 | if len(os.Args) != 2 { 24 | log.Fatal("usage: weave input.md\n") 25 | } 26 | 27 | f, err := os.Open(os.Args[1]) 28 | if err != nil { 29 | log.Fatal(err) 30 | } 31 | defer f.Close() 32 | 33 | fmt.Println("") 34 | 35 | // Pass 1. 36 | var toc []string 37 | in := bufio.NewScanner(f) 38 | for in.Scan() { 39 | line := in.Text() 40 | if line == "" || (line[0] != '#' && line[0] != '%') { 41 | continue 42 | } 43 | line = strings.TrimSpace(line) 44 | if line == "%toc" { 45 | toc = nil 46 | } else if strings.HasPrefix(line, "# ") || strings.HasPrefix(line, "## ") { 47 | words := strings.Fields(line) 48 | depth := len(words[0]) 49 | words = words[1:] 50 | text := strings.Join(words, " ") 51 | for i := range words { 52 | words[i] = strings.ToLower(words[i]) 53 | } 54 | line = fmt.Sprintf("%s1. [%s](#%s)", 55 | strings.Repeat("\t", depth-1), text, strings.Join(words, "-")) 56 | toc = append(toc, line) 57 | } 58 | } 59 | 60 | // Pass 2. 61 | if _, err := f.Seek(0, os.SEEK_SET); err != nil { 62 | log.Fatalf("can't rewind input: %v", err) 63 | } 64 | in = bufio.NewScanner(f) 65 | for in.Scan() { 66 | line := in.Text() 67 | switch { 68 | case strings.HasPrefix(line, "%toc"): // ToC 69 | for _, h := range toc { 70 | fmt.Println(h) 71 | } 72 | case strings.HasPrefix(line, "%include"): 73 | words := strings.Fields(line) 74 | if len(words) < 2 { 75 | log.Fatal(line) 76 | } 77 | filename := words[1] 78 | 79 | // Show caption unless '-' follows. 80 | if len(words) < 4 || words[3] != "-" { 81 | fmt.Printf(" // go get golang.org/x/example/gotypes/%s\n\n", 82 | filepath.Dir(filename)) 83 | } 84 | 85 | section := "" 86 | if len(words) > 2 { 87 | section = words[2] 88 | } 89 | s, err := include(filename, section) 90 | if err != nil { 91 | log.Fatal(err) 92 | } 93 | fmt.Println("```") 94 | fmt.Println(cleanListing(s)) // TODO(adonovan): escape /^```/ in s 95 | fmt.Println("```") 96 | default: 97 | fmt.Println(line) 98 | } 99 | 100 | } 101 | } 102 | 103 | // include processes an included file, and returns the included text. 104 | // Only lines between those matching !+tag and !-tag will be returned. 105 | // This is true even if tag=="". 106 | func include(file, tag string) (string, error) { 107 | f, err := os.Open(file) 108 | if err != nil { 109 | return "", err 110 | } 111 | defer f.Close() 112 | 113 | startre, err := regexp.Compile("!\\+" + tag + "$") 114 | if err != nil { 115 | return "", err 116 | } 117 | endre, err := regexp.Compile("!\\-" + tag + "$") 118 | if err != nil { 119 | return "", err 120 | } 121 | 122 | var text bytes.Buffer 123 | in := bufio.NewScanner(f) 124 | var on bool 125 | for in.Scan() { 126 | line := in.Text() 127 | switch { 128 | case startre.MatchString(line): 129 | on = true 130 | case endre.MatchString(line): 131 | on = false 132 | case on: 133 | text.WriteByte('\t') 134 | text.WriteString(line) 135 | text.WriteByte('\n') 136 | } 137 | } 138 | if text.Len() == 0 { 139 | return "", fmt.Errorf("no lines of %s matched tag %q", file, tag) 140 | } 141 | return text.String(), nil 142 | } 143 | 144 | func isBlank(line string) bool { return strings.TrimSpace(line) == "" } 145 | 146 | func indented(line string) bool { 147 | return strings.HasPrefix(line, " ") || strings.HasPrefix(line, "\t") 148 | } 149 | 150 | // cleanListing removes entirely blank leading and trailing lines from 151 | // text, and removes n leading tabs. 152 | func cleanListing(text string) string { 153 | lines := strings.Split(text, "\n") 154 | 155 | // remove minimum number of leading tabs from all non-blank lines 156 | tabs := 999 157 | for i, line := range lines { 158 | if strings.TrimSpace(line) == "" { 159 | lines[i] = "" 160 | } else { 161 | if n := leadingTabs(line); n < tabs { 162 | tabs = n 163 | } 164 | } 165 | } 166 | for i, line := range lines { 167 | if line != "" { 168 | line := line[tabs:] 169 | lines[i] = line // remove leading tabs 170 | } 171 | } 172 | 173 | // remove leading blank lines 174 | for len(lines) > 0 && lines[0] == "" { 175 | lines = lines[1:] 176 | } 177 | // remove trailing blank lines 178 | for len(lines) > 0 && lines[len(lines)-1] == "" { 179 | lines = lines[:len(lines)-1] 180 | } 181 | return strings.Join(lines, "\n") 182 | } 183 | 184 | func leadingTabs(s string) int { 185 | var i int 186 | for i = 0; i < len(s); i++ { 187 | if s[i] != '\t' { 188 | break 189 | } 190 | } 191 | return i 192 | } 193 | -------------------------------------------------------------------------------- /hello/hello.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 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 | package main 18 | 19 | import ( 20 | "fmt" 21 | 22 | "golang.org/x/example/stringutil" 23 | ) 24 | 25 | func main() { 26 | fmt.Println(stringutil.Reverse("!selpmaxe oG ,olleH")) 27 | } 28 | -------------------------------------------------------------------------------- /outyet/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:onbuild 2 | EXPOSE 8080 3 | -------------------------------------------------------------------------------- /outyet/containers.yaml: -------------------------------------------------------------------------------- 1 | version: v1beta2 2 | containers: 3 | - name: outyet 4 | image: adg1/outyet 5 | ports: 6 | - name: http 7 | hostPort: 80 8 | containerPort: 8080 9 | -------------------------------------------------------------------------------- /outyet/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 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 | // outyet is a web server that announces whether or not a particular Go version 18 | // has been tagged. 19 | package main 20 | 21 | import ( 22 | "expvar" 23 | "flag" 24 | "fmt" 25 | "html/template" 26 | "log" 27 | "net/http" 28 | "sync" 29 | "time" 30 | ) 31 | 32 | // Command-line flags. 33 | var ( 34 | httpAddr = flag.String("http", ":8080", "Listen address") 35 | pollPeriod = flag.Duration("poll", 5*time.Second, "Poll period") 36 | version = flag.String("version", "1.4", "Go version") 37 | ) 38 | 39 | const baseChangeURL = "https://go.googlesource.com/go/+/" 40 | 41 | func main() { 42 | flag.Parse() 43 | changeURL := fmt.Sprintf("%sgo%s", baseChangeURL, *version) 44 | http.Handle("/", NewServer(*version, changeURL, *pollPeriod)) 45 | log.Fatal(http.ListenAndServe(*httpAddr, nil)) 46 | } 47 | 48 | // Exported variables for monitoring the server. 49 | // These are exported via HTTP as a JSON object at /debug/vars. 50 | var ( 51 | hitCount = expvar.NewInt("hitCount") 52 | pollCount = expvar.NewInt("pollCount") 53 | pollError = expvar.NewString("pollError") 54 | pollErrorCount = expvar.NewInt("pollErrorCount") 55 | ) 56 | 57 | // Server implements the outyet server. 58 | // It serves the user interface (it's an http.Handler) 59 | // and polls the remote repository for changes. 60 | type Server struct { 61 | version string 62 | url string 63 | period time.Duration 64 | 65 | mu sync.RWMutex // protects the yes variable 66 | yes bool 67 | } 68 | 69 | // NewServer returns an initialized outyet server. 70 | func NewServer(version, url string, period time.Duration) *Server { 71 | s := &Server{version: version, url: url, period: period} 72 | go s.poll() 73 | return s 74 | } 75 | 76 | // poll polls the change URL for the specified period until the tag exists. 77 | // Then it sets the Server's yes field true and exits. 78 | func (s *Server) poll() { 79 | for !isTagged(s.url) { 80 | pollSleep(s.period) 81 | } 82 | s.mu.Lock() 83 | s.yes = true 84 | s.mu.Unlock() 85 | pollDone() 86 | } 87 | 88 | // Hooks that may be overridden for integration tests. 89 | var ( 90 | pollSleep = time.Sleep 91 | pollDone = func() {} 92 | ) 93 | 94 | // isTagged makes an HTTP HEAD request to the given URL and reports whether it 95 | // returned a 200 OK response. 96 | func isTagged(url string) bool { 97 | pollCount.Add(1) 98 | r, err := http.Head(url) 99 | if err != nil { 100 | log.Print(err) 101 | pollError.Set(err.Error()) 102 | pollErrorCount.Add(1) 103 | return false 104 | } 105 | return r.StatusCode == http.StatusOK 106 | } 107 | 108 | // ServeHTTP implements the HTTP user interface. 109 | func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { 110 | hitCount.Add(1) 111 | s.mu.RLock() 112 | data := struct { 113 | URL string 114 | Version string 115 | Yes bool 116 | }{ 117 | s.url, 118 | s.version, 119 | s.yes, 120 | } 121 | s.mu.RUnlock() 122 | err := tmpl.Execute(w, data) 123 | if err != nil { 124 | log.Print(err) 125 | } 126 | } 127 | 128 | // tmpl is the HTML template that drives the user interface. 129 | var tmpl = template.Must(template.New("tmpl").Parse(` 130 |
131 |

Is Go {{.Version}} out yet?

132 |

133 | {{if .Yes}} 134 | YES! 135 | {{else}} 136 | No. :-( 137 | {{end}} 138 |

139 |
140 | `)) 141 | -------------------------------------------------------------------------------- /outyet/main_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 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 | package main 18 | 19 | import ( 20 | "net/http" 21 | "net/http/httptest" 22 | "strings" 23 | "testing" 24 | "time" 25 | ) 26 | 27 | // statusHandler is an http.Handler that writes an empty response using itself 28 | // as the response status code. 29 | type statusHandler int 30 | 31 | func (h *statusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 32 | w.WriteHeader(int(*h)) 33 | } 34 | 35 | func TestIsTagged(t *testing.T) { 36 | // Set up a fake "Google Code" web server reporting 404 not found. 37 | status := statusHandler(http.StatusNotFound) 38 | s := httptest.NewServer(&status) 39 | defer s.Close() 40 | 41 | if isTagged(s.URL) { 42 | t.Fatal("isTagged == true, want false") 43 | } 44 | 45 | // Change fake server status to 200 OK and try again. 46 | status = http.StatusOK 47 | 48 | if !isTagged(s.URL) { 49 | t.Fatal("isTagged == false, want true") 50 | } 51 | } 52 | 53 | func TestIntegration(t *testing.T) { 54 | status := statusHandler(http.StatusNotFound) 55 | ts := httptest.NewServer(&status) 56 | defer ts.Close() 57 | 58 | // Replace the pollSleep with a closure that we can block and unblock. 59 | sleep := make(chan bool) 60 | pollSleep = func(time.Duration) { 61 | sleep <- true 62 | sleep <- true 63 | } 64 | 65 | // Replace pollDone with a closure that will tell us when the poller is 66 | // exiting. 67 | done := make(chan bool) 68 | pollDone = func() { done <- true } 69 | 70 | // Put things as they were when the test finishes. 71 | defer func() { 72 | pollSleep = time.Sleep 73 | pollDone = func() {} 74 | }() 75 | 76 | s := NewServer("1.x", ts.URL, 1*time.Millisecond) 77 | 78 | <-sleep // Wait for poll loop to start sleeping. 79 | 80 | // Make first request to the server. 81 | r, _ := http.NewRequest("GET", "/", nil) 82 | w := httptest.NewRecorder() 83 | s.ServeHTTP(w, r) 84 | if b := w.Body.String(); !strings.Contains(b, "No.") { 85 | t.Fatalf("body = %s, want no", b) 86 | } 87 | 88 | status = http.StatusOK 89 | 90 | <-sleep // Permit poll loop to stop sleeping. 91 | <-done // Wait for poller to see the "OK" status and exit. 92 | 93 | // Make second request to the server. 94 | w = httptest.NewRecorder() 95 | s.ServeHTTP(w, r) 96 | if b := w.Body.String(); !strings.Contains(b, "YES!") { 97 | t.Fatalf("body = %q, want yes", b) 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /stringutil/reverse.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 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 | // Package stringutil contains utility functions for working with strings. 18 | package stringutil 19 | 20 | // Reverse returns its argument string reversed rune-wise left to right. 21 | func Reverse(s string) string { 22 | r := []rune(s) 23 | for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { 24 | r[i], r[j] = r[j], r[i] 25 | } 26 | return string(r) 27 | } 28 | -------------------------------------------------------------------------------- /stringutil/reverse_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 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 | package stringutil 18 | 19 | import "testing" 20 | 21 | func TestReverse(t *testing.T) { 22 | for _, c := range []struct { 23 | in, want string 24 | }{ 25 | {"Hello, world", "dlrow ,olleH"}, 26 | {"Hello, 世界", "界世 ,olleH"}, 27 | {"", ""}, 28 | } { 29 | got := Reverse(c.in) 30 | if got != c.want { 31 | t.Errorf("Reverse(%q) == %q, want %q", c.in, got, c.want) 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /template/image.tmpl: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |
3 | {{.Title}} 4 |
5 | {{end}} 6 | 7 | {{define "sidebar"}} 8 | Back 9 | {{end}} 10 | -------------------------------------------------------------------------------- /template/index.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{.Title}} 6 | 17 | 18 | 19 |

{{.Title}}

20 | 21 | 34 | 35 | {{block "content" .}} 36 |
37 | {{.Body}} 38 |
39 | {{end}} 40 | 41 | 42 | -------------------------------------------------------------------------------- /template/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 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 | // Command template is a trivial web server that uses the text/template (and 18 | // html/template) package's "block" feature to implement a kind of template 19 | // inheritance. 20 | // 21 | // It should be executed from the directory in which the source resides, 22 | // as it will look for its template files in the current directory. 23 | package main 24 | 25 | import ( 26 | "html/template" 27 | "log" 28 | "net/http" 29 | "strings" 30 | ) 31 | 32 | func main() { 33 | http.HandleFunc("/", indexHandler) 34 | http.HandleFunc("/image/", imageHandler) 35 | log.Fatal(http.ListenAndServe("localhost:8080", nil)) 36 | } 37 | 38 | // indexTemplate is the main site template. 39 | // The default template includes two template blocks ("sidebar" and "content") 40 | // that may be replaced in templates derived from this one. 41 | var indexTemplate = template.Must(template.ParseFiles("index.tmpl")) 42 | 43 | // Index is a data structure used to populate an indexTemplate. 44 | type Index struct { 45 | Title string 46 | Body string 47 | Links []Link 48 | } 49 | 50 | type Link struct { 51 | URL, Title string 52 | } 53 | 54 | // indexHandler is an HTTP handler that serves the index page. 55 | func indexHandler(w http.ResponseWriter, r *http.Request) { 56 | data := &Index{ 57 | Title: "Image gallery", 58 | Body: "Welcome to the image gallery.", 59 | } 60 | for name, img := range images { 61 | data.Links = append(data.Links, Link{ 62 | URL: "/image/" + name, 63 | Title: img.Title, 64 | }) 65 | } 66 | if err := indexTemplate.Execute(w, data); err != nil { 67 | log.Println(err) 68 | } 69 | } 70 | 71 | // imageTemplate is a clone of indexTemplate that provides 72 | // alternate "sidebar" and "content" templates. 73 | var imageTemplate = template.Must(template.Must(indexTemplate.Clone()).ParseFiles("image.tmpl")) 74 | 75 | // Image is a data structure used to populate an imageTemplate. 76 | type Image struct { 77 | Title string 78 | URL string 79 | } 80 | 81 | // imageHandler is an HTTP handler that serves the image pages. 82 | func imageHandler(w http.ResponseWriter, r *http.Request) { 83 | data, ok := images[strings.TrimPrefix(r.URL.Path, "/image/")] 84 | if !ok { 85 | http.NotFound(w, r) 86 | return 87 | } 88 | if err := imageTemplate.Execute(w, data); err != nil { 89 | log.Println(err) 90 | } 91 | } 92 | 93 | // images specifies the site content: a collection of images. 94 | var images = map[string]*Image{ 95 | "go": {"The Go Gopher", "https://golang.org/doc/gopher/frontpage.png"}, 96 | "google": {"The Google Logo", "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"}, 97 | } 98 | --------------------------------------------------------------------------------