<p>No, really. How do you get one?</p>
<p>According to <code>go doc go/ast | grep Package</code>...</p>
<pre><code>Package ast declares the types used to represent syntax trees for Go
func FilterPackage(pkg *Package, f Filter) bool
func PackageExports(pkg *Package) bool
func MergePackageFiles(pkg *Package, mode MergeMode) *File
type Package struct{ ... }
func NewPackage(fset *token.FileSet, files map[string]*File, importer Importer, ...) (*Package, error)
</code></pre>
<p>...there's only one way:</p>
<pre><code>func NewPackage(fset *token.FileSet, files map[string]*File, importer Importer, universe *Scope) (*Package, error)
</code></pre>
<p>I tried passing nil for importer and universe, but I got parse errors like "undeclared name: string". So, how do I get an ast.Importer and the universe *ast.Scope that will work in the general case?</p>
<p>I grepped stdlib and golang.org/x/tools code and found an ast.Importer implementation called "poorMansImporter", but the code indicates it's a half-assed implementation that does some guesswork. It doesn't seem generally useful.</p>
<p>I see a types.Universe, which is a *types.Scope, but I need an *ast.Scope. And there's no ast.Universe *ast.Scope.</p>
<p>Argh! Help! :)</p>
<hr/>**评论:**<br/><br/>zekjur: <pre><p>Check out <a href="http://golang.org/s/types-tutorial">http://golang.org/s/types-tutorial</a>, specifically <a href="https://github.com/golang/example/tree/master/gotypes#an-example">https://github.com/golang/example/tree/master/gotypes#an-example</a> :)</p></pre>zekjur: <pre><p>If you’re using Go ≥ 1.9, <code>importer.For("source", nil)</code> is the most useful/correct importer (because it doesn’t require up-to-date export data files to be present), but also slower than <code>importer.Default()</code>.</p></pre>sh41: <pre><p>I've been looking for an answer for the last 4 years too. This is the best I've found. But I'm still looking for a better way.</p>
<p><a href="https://github.com/shurcooL/cmd/blob/3775d1a67e78fba6a8380e30337340465a0b30e3/gorepogen/main.go#L80-L93" rel="nofollow">https://github.com/shurcooL/cmd/blob/3775d1a67e78fba6a8380e30337340465a0b30e3/gorepogen/main.go#L80-L93</a></p></pre>indil7: <pre><p>Ha, that's EXACTLY what I did as a workaround! That's funny. :)</p>
<p>It leaves ast.Package.Imports empty, though, and, presumably, as the NewPackage doc says, undeclared identifiers unresolved. I was hoping to do it the "right" way, if you know what I mean.</p>
<p>Edit: I think there's a Package.Scope that it also leaves nil.</p></pre>sh41: <pre><p>Yes, I know what you mean. I haven't found a better way but will gladly update my code if I ever do.</p>
<p>That said, the main question is what do you need the *ast.Package for? If it's for creating a *doc.Package, the above fields should be sufficient. As far as I know, there's no other use for *ast.Package.</p>
<p>For all other things, you'll either use go/build to get a *build.Package, or use go/types if you want to do type analysis.</p></pre>indil7: <pre><p>It's for code generation, so I need the full AST. Another use might be something like gofmt or other syntax transformations.</p></pre>matttproud: <pre><p>I recommend looking at cmd/vet or cmd/lint source as an example. They are an easy read: <a href="https://github.com/golang/go/tree/master/src/cmd/vet" rel="nofollow">https://github.com/golang/go/tree/master/src/cmd/vet</a></p></pre>daydreamdrunk: <pre><p>I usually use parser.ParseDir like this: </p>
<p><a href="https://play.golang.org/p/nbqLAolgbT" rel="nofollow">https://play.golang.org/p/nbqLAolgbT</a></p>
<p>Though it does not run on the playground, complaining that $GOPATH's not set. </p></pre>indil7: <pre><p>The problem with that approach is that it doesn't work for packages with build tags. For example, for package runtime: "cannot load package: [...]/src/runtime/defs1_netbsd_arm.go:7:2: _EINTR redeclared in this block". Do you know a way around that for ParseDir?</p></pre>daydreamdrunk: <pre><p>The go/build portion in that listing takes care of all that</p>
<p>Edit to clarify: it handles all the stuff with gopath and build tags and gives a list of the files that apply to the given build.Context (which defaults to the default context which is the current GOOS/GOARCH).</p>
<p>Note the fileCheck closure: it tells ParseDir to only parse the files which go/build identifies. (It would be really nice if this were helper on build.Package or there was a helper func in parse, but it's not a lot of code to write.)</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传