<p>The past month I've been learning Go, and I'm really starting to feel comfortable with it and find pieces that are interesting and exciting (as initially it wasn't so). </p>
<p>I've been looking through Golang projects and one thing that stands out strongly that I find really difficult is how functions are scoped within a package in relation to files in that package. </p>
<p>For example, in <code>package main</code>, you have <code>main.go</code> file that uses <code>someRandomFunc()</code>, and this function could be declared in any of the files in this package, such as in <code>api.go</code>, but the usage in <code>main.go</code> doesn't make this explicit where it comes from. </p>
<p>The bias, or my experience of what I'm used to, is doing something like this:</p>
<p><code>index.js</code>:</p>
<p><code>import { someRandomFunc } from './api'</code></p>
<p><code>api.js</code>:</p>
<p><code>export function someRandomFunc () { ... }</code></p>
<p>What I find so hard to follow is that when I am orientating myself to a new project, I'll start looking in <code>main.go</code> and see some use of functions, then I'm asking myself, 'where was that declared?' and have to grep the directory for it.</p>
<p>I've heard a lot about making things simple and clear in Go, but for me, this is complicated. </p>
<p>I'd be glad to hear more experienced Gopher's thoughts on this - perhaps it's not a problem for you and you can point out where I'm approaching it incorrectly/poorly, or maybe you overcame this somehow. </p>
<hr/>**评论:**<br/><br/>dlsniper: <pre><p>Also, if you use Chrome, check the SourceGraph extension for Chrome and Github: <a href="https://chrome.google.com/webstore/detail/sourcegraph-for-github/dgjhfomjieaadpoljlnidmbgkdffpack?hl=en" rel="nofollow">https://chrome.google.com/webstore/detail/sourcegraph-for-github/dgjhfomjieaadpoljlnidmbgkdffpack?hl=en</a></p></pre>shovelpost: <pre><p>With vim and vim-go it's just as easy as <code>gd</code> to quickly go to the definition of a function.</p></pre>seufert: <pre><p>Actually in most editors with their go support: Emacs, Sublime and Visual Studio Code and as mentioned by dlsniper Intellij.</p></pre>jaetteintemer: <pre><p>Is third party tooling then the only way to work through this? I guess after hearing so much about the philosophy of Go -- that things should be clear and simple -- I find the lack of language-level clarity in this surprising. </p></pre>itsmontoya: <pre><p>Almost every language has tooling. Some of the "best" languages have gained that status as a result of incredible tooling.</p></pre>hahainternet: <pre><blockquote>
<p>I find the lack of language-level clarity in this surprising</p>
</blockquote>
<p>There's a number of reasons behind this, for a start, Go code is compiled to a single binary, not a series of .pyc files for example (yes I know about .o) and as a result the packages become actually one package. It would be awful to say "import github.com/someurl from github.com/someurl/packagefile"</p>
<p>Next, while bare functions are completely acceptable, most functions should be attached to types and packages also named after the types or a subset. Instead of someRandomFunc it should potentially be Item.RandomFunc and the code can belong in item.go.</p>
<p>These rules aren't universal, and it's really down to how you personally prefer things, but this is how I see it.</p></pre>jaetteintemer: <pre><p>Thanks for your thoughtful reply. In your example of <code>item.go</code>, do you mean that <code>RandomFunc</code> is a method on <code>Item</code>, or is it more like how there is <code>flag.Parse</code> ? </p></pre>exit-gate: <pre><blockquote>
<p>I find the lack of language-level clarity in this surprising</p>
</blockquote>
<p>What does that statement mean? I feel like I'm missing something here (you make vague claims, with no evidence of what you're talking about)</p></pre>globalgobble: <pre><p>What's the package for emacs ?</p></pre>i4k: <pre><p><a href="https://github.com/dominikh/go-mode.el" rel="nofollow">https://github.com/dominikh/go-mode.el</a></p></pre>jaetteintemer: <pre><p>Cool! that's helpful to know at least.. </p></pre>The_Sly_Marbo: <pre><p>Go's syntax also makes it really easy to search with grep. Find function <code>foo()</code> with <code>grep -n 'func foo' *.go</code> and method <code>foo.bar()</code> with <code>grep -n '\) bar' *.go</code>.</p></pre>dlsniper: <pre><p>With IntelliJ you can pretty much follow both scopes and as well define different colors for them as well as notice when you are shadowing a variable.</p></pre>earthboundkid: <pre><p>This should not be a problem in well written code. In Go, files in the same package/directory share a namespace, but well written code should have very little in package main and most code in other packages. Treating directories as one package means you don't need to make files huge to satisfy your API. It may be that your package only exposes a few functions to the public but has an extensive internal logic. Because directories are one namespace, you can still arrange the internal code well. </p></pre>jaetteintemer: <pre><p>In line with what you're sharing here, are there best practices for where to place what is exported? Also, are you talking literally about the <code>/internal</code> directory?</p></pre>exit-gate: <pre><blockquote>
<p>What I find so hard to follow is that when I am orientating myself to a new project, I'll start looking in main.go and see some use of functions, then I'm asking myself, 'where was that declared?' and have to grep the directory for it.</p>
<p>I've heard a lot about making things simple and clear in Go, but for me, this is complicated. </p>
</blockquote>
<p>I find this a bit strange... If things are in multiple files how else are you going to find things without grepping or using some other dedicated tool?</p>
<p>Serious question: how do you go about finding things in the same file, and how is it different to finding in other files? I can't remember the last time I used an editor that didn't have some builtin indexing available to find symbols in the entire project or one that was incapable of searching through all files in the project.</p></pre>jaetteintemer: <pre><p>Well, I outlined in my first post how I'm used to this from Node.. I see your point, too, though</p></pre>dinkumator: <pre><p>It won't work (easily) for unexported functions, but you can also run godoc locally to show all the package-level exported functions:</p>
<pre><code>godoc -http=:6060
</code></pre>
<p>Then add <code>?m=all</code> to the doc url to see unexported types/functions:
<a href="http://localhost:6060/pkg/net/?m=all" rel="nofollow">http://localhost:6060/pkg/net/?m=all</a></p>
<p>This won't work for <code>package main</code> without a modified godoc though. <a href="https://github.com/golang/go/issues/5727" rel="nofollow">CL here</a> if that's what you want...</p></pre>jaetteintemer: <pre><p>Awesome, thanks!</p></pre>i4k: <pre><p>If only what you want is the documentation of the func/const/var then you would like <code>go doc</code>.</p>
<pre><code>go doc somepkg.SomeFunc
</code></pre>
<p>To look for unexported symbols:</p>
<pre><code>go doc -u somefunc
</code></pre></pre>thepciet: <pre><p>I struggle with this too. Organizing symbols is a significant task in Go for anything other than very small projects.</p></pre>icholy: <pre><p>it really isn't</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传