TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Uber Go Style Guide

309 pointsby robfigover 5 years ago

21 comments

sanxiynover 5 years ago
&quot;Copy Slices and Maps at Boundaries. Slices and maps contain pointers to the underlying data so be wary of scenarios when they need to be copied. Keep in mind that users can modify a map or slice you received as an argument if you store a reference to it. Similarly, be wary of user modifications to maps or slices exposing internal state.&quot;<p>This could be used as an ad for Rust borrow checker, verbatim. You can&#x27;t modify a map or slice you passed as an argument if a reference to it is stored!
评论 #21225823 未加载
评论 #21227790 未加载
评论 #21226582 未加载
评论 #21226453 未加载
评论 #21230628 未加载
评论 #21226908 未加载
评论 #21228988 未加载
heroHACK17over 5 years ago
I really like the horizontal &#x27;Good&#x2F;Bad&#x27; code comparisons in this guide.<p>I didn&#x27;t realize how horizontal vs. vertical code comparison affects readability; IMO horizontal is MUCH more readable.<p>Example: <a href="https:&#x2F;&#x2F;github.com&#x2F;uber-go&#x2F;guide&#x2F;blob&#x2F;master&#x2F;style.md#defer-to-clean-up" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;uber-go&#x2F;guide&#x2F;blob&#x2F;master&#x2F;style.md#defer-...</a>
评论 #21229788 未加载
评论 #21228930 未加载
knorkerover 5 years ago
Pretty good. Some opinions that fall under &quot;be consistent within our code base&quot; (which is why Uber should have a style guide at all), so all good.<p>Just one comment though:<p>&gt; Embedding sync.Mutex<p>Never do this on an exported type. If you embed sync.Mutex that makes &quot;Lock&quot; and &quot;Unlock&quot; part of <i>your</i> exported interface. Now the caller of your API doesn&#x27;t know if <i>they</i> are supposed to call Lock&#x2F;Unlock, or if this is a pure internal implementation detail.<p>your `type Stats` &quot;isn&#x27;t&quot; a mutex. It <i>has</i> a mutex.
评论 #21226185 未加载
评论 #21226272 未加载
jrockwayover 5 years ago
Something that I don&#x27;t see style guides addressing, but think they should, is how to cancel work when the caller no longer cares about the answer. (Consider an aborted RPC, or someone pressing the &quot;stop&quot; button in their browser.)<p>A lot of people will do things like:<p><pre><code> func (s *Server) HandleFoo(ctx context.Context, in *input) status { ch &lt;- workFor(in) return status.Accepted } </code></pre> This will block on the channel write even if the context becomes cancelled. Instead, you really need to be explicit about what you want to block:<p><pre><code> func (s *Server) HandleFoo(ctx context.Context, in *input) status { select { case ch &lt;- workFor(in): return status.Accepted case &lt;- ctx.Done(): return status.Error(&quot;handle foo: wait for work to be accepted: %w&quot;, ctx.Err()) } } </code></pre> Now we don&#x27;t wait for the work to be accepted if the caller decides it doesn&#x27;t care about the job anymore.<p>My impression from digging around the open source world is that nobody except me cares about this. So maybe I&#x27;m just crazy. But I really like not leaking goroutines on long-running programs, making Control-C behave gracefully, etc.
评论 #21230551 未加载
评论 #21228664 未加载
评论 #21228731 未加载
评论 #21228626 未加载
评论 #21235203 未加载
ra7over 5 years ago
Is Go the primary language in Uber now? I see a lot of tools written in Go coming out of Uber. What kind of services inside Uber is Go used for?
评论 #21226336 未加载
评论 #21226347 未加载
评论 #21225782 未加载
评论 #21225895 未加载
评论 #21227186 未加载
dev_dullover 5 years ago
A style guide with benchmarks that can be read in a single cup of coffee. Very nice and one of the reasons I enjoy Go!
sidllsover 5 years ago
The section on exporting functions to check errors just exposes Go&#x27;s weakness in error checking. It&#x27;s unnecessarily verbose.
评论 #21227474 未加载
ArtWombover 5 years ago
No buffered channels, or if you do, you must provide a very strong rationale ;)<p>I still use them quite a bit. Particularly synchronizing large rule sets as bit arrays. Of course you can use sync.Wait instead. But make(chan bool, N) semantics are just more convenient. It&#x27;s stealth synchronization as a by-product. And hence the warnings about determinism!
评论 #21226431 未加载
评论 #21229074 未加载
tapirlover 5 years ago
Copy Slices and Maps at Boundaries: <a href="https:&#x2F;&#x2F;github.com&#x2F;uber-go&#x2F;guide&#x2F;blob&#x2F;master&#x2F;style.md#copy-slices-and-maps-at-boundaries" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;uber-go&#x2F;guide&#x2F;blob&#x2F;master&#x2F;style.md#copy-s...</a><p>The suggested good clone is not very efficient: <a href="https:&#x2F;&#x2F;github.com&#x2F;go101&#x2F;go101&#x2F;wiki&#x2F;How-to-efficiently-clone-a-slice%3F" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;go101&#x2F;go101&#x2F;wiki&#x2F;How-to-efficiently-clone...</a><p>In fact, I prefer the suggested bad one instead. We should let the caller to determine whether or not a clone is needed.<p>--------------------------<p>Start Enums at One: <a href="https:&#x2F;&#x2F;github.com&#x2F;uber-go&#x2F;guide&#x2F;blob&#x2F;master&#x2F;style.md#start-enums-at-one" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;uber-go&#x2F;guide&#x2F;blob&#x2F;master&#x2F;style.md#start-...</a> Any reason here? (Edit: I just missed the reason. However, I think there should be a default value for most enums and most of the default values should zero.)<p>--------------------------<p>Local Variable Declarations: <a href="https:&#x2F;&#x2F;github.com&#x2F;uber-go&#x2F;guide&#x2F;blob&#x2F;master&#x2F;style.md#local-variable-declarations" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;uber-go&#x2F;guide&#x2F;blob&#x2F;master&#x2F;style.md#local-...</a><p>Personally, I prefer &quot;var x = ...&quot; and think short variables should be used as limited as possible. I remember that Go team has a not-very-concrete plan to depreciate short variable declarations.<p>--------------------------<p>Avoid Naked Parameters: <a href="https:&#x2F;&#x2F;github.com&#x2F;uber-go&#x2F;guide&#x2F;blob&#x2F;master&#x2F;style.md#avoid-naked-parameters" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;uber-go&#x2F;guide&#x2F;blob&#x2F;master&#x2F;style.md#avoid-...</a><p>This suggestion has its own drawback. When a parameter name changed, all the places using it must be modified to keep consistent. This is one reason why Go team rejected named arguments.<p>If this must be done, I recommend to define and use some named bool constants instead.
评论 #21229527 未加载
Groxxover 5 years ago
I&#x27;ll throw in one request for functional options <i>as written here</i>: please don&#x27;t use closures to capture the data.<p>If you use closures, it&#x27;s <i>nearly</i> impossible to compare the results for equality in tests or code that might care to validate &#x2F; deduplicate &#x2F; whatever those args. You can achieve it with a moderate amount of heavily-implementation-dependent reflection (get the func type, construct arg(s), call func, check result), but that&#x27;s about it.<p>Please just use values as the backing type. `type thing int` is utterly trivial to compare if needed, by comparison - just use `==`. Any code anywhere can construct the same argument in the same way and `==` to see if what they are checking is part of the args, and you&#x27;re still not binding yourself to a specific implementation-type that&#x27;ll later risk a compile-time failure.<p>(if users are casting to the private `int` type to check stuff, yea, it breaks - but the reflection-to-read-closure approach has that same problem, you can&#x27;t stop it)<p>Also, in my experience, the &quot;loop and apply&quot; pattern tends to fall apart rather quickly, and you start wanting more complicated interactions between args &#x2F; validation that you didn&#x27;t pass both &quot;include deleted&quot; and &quot;exclude deleted&quot; and the second just silently clobbered the first. With values you can pretty easily loop and switch on the type and do whatever you need.
评论 #21233430 未加载
logicalleeover 5 years ago
Not an expert, but could someone explain why it says: &quot;Panic&#x2F;recover is not an error handling strategy. A program must panic only when something irrecoverable happens such as a nil dereference.&quot; Why is that any more irrecoverable than anything else? (You can check if it&#x27;s nil before referencing it, right?)
评论 #21229252 未加载
评论 #21231334 未加载
aloknnikhilover 5 years ago
&gt; Use go.uber.org&#x2F;atomic Atomic operations with the sync&#x2F;atomic package operate on the raw types (int32, int64, etc.) so it is easy to forget to use the atomic operation to read or modify the variables. go.uber.org&#x2F;atomic adds type safety to these operations by hiding the underlying type.<p>I don&#x27;t agree with this guideline. When you anyway have to remember to invoke an intrinsic function on the variable (unlike, say, operator overloading), I wonder why it&#x27;s necessary to include yet another dependency that&#x27;s just a wrapper for sync&#x2F;atomic all because the developer doesn&#x27;t pay attention to the right use of atomics.
palebluedotover 5 years ago
The preference of channel size being unbuffered or just 1 is interesting. That seems like something specific to a problem domain; for instance, in projects I am working on now, having a large buffered channel (1000s deep) is useful for worker queues of thousands of goroutines, that all read from a task feeder channel. This type of queuing seems go-idiomatic, and negates the need for additional synchronization. In this case, the backpressure blocking on writers is a feature.
评论 #21230583 未加载
评论 #21229861 未加载
评论 #21229864 未加载
评论 #21229708 未加载
marcrosoftover 5 years ago
It’s nice that go barely needs a style guide because of go fmt.
fryhover 5 years ago
I am not a Go programmer, but this seems like a really nice guide. Is there anything similar for Python or C++?
评论 #21229273 未加载
abbot2over 5 years ago
I find it amusing that the advice in the style guide gives a good example contradicting another good example, and contains a subtle bug.<p>In the &quot;Reduce Scope of Variables&quot;, second good example leaks an open file when WriteString fails, because it doesn&#x27;t follow the own advice of &quot;Defer to Clean Up&quot; if you are curious.<p>(Handling that properly with a defer is a bit more tricky - something like <a href="https:&#x2F;&#x2F;play.golang.org&#x2F;p&#x2F;l1PeWM3Tisg" rel="nofollow">https:&#x2F;&#x2F;play.golang.org&#x2F;p&#x2F;l1PeWM3Tisg</a>).<p>Update: style guide was fixed after this report :) It was this if you wonder: <a href="https:&#x2F;&#x2F;github.com&#x2F;uber-go&#x2F;guide&#x2F;blob&#x2F;a53ee0bef8c0b11b52340dbbc82e8be37f4a88d2&#x2F;style.md" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;uber-go&#x2F;guide&#x2F;blob&#x2F;a53ee0bef8c0b11b52340d...</a>
thinkingkongover 5 years ago
How would you enforce any of these? Are these guides or reasons to not accept PRs? Seems like it would be worth encoding in a tool if this is for teams.
评论 #21227441 未加载
nergalover 5 years ago
Underscore in globals. Is that really go best practice?
评论 #21229934 未加载
评论 #21265298 未加载
codesushi42over 5 years ago
Why is this better than Google&#x27;s?
评论 #21228472 未加载
thallavajhulaover 5 years ago
Correct me if I&#x27;m wrong, but, isn&#x27;t the primary purpose of `gofmt` to solve having to deal with style guides like these in the community?
评论 #21225838 未加载
jlokierover 5 years ago
This recommendation surprised me:<p><pre><code> if err := ioutil.WriteFile(name, data, 0644); err != nil { return err } </code></pre> I&#x27;ve often seen guides for many languages that say don&#x27;t use an assignment as an &quot;if&quot; condition. It may be a typo, and so is a source of errors, or it hides errors. Many compilers warn about it, and some people will consider it poor enough to refactor it out.<p>Of course it&#x27;s not the assignment which is being tested in the Go code above. But it might as well be.<p>In Swift, Rust, Clojure and Perl, &quot;if let&quot; is common. (&quot;if-let&quot; in Clojure, &quot;if my&quot; in Perl). It&#x27;s useful, and conforms well to the idea of limiting scope of the tested variable. I use it all the time.<p>So scope limiting in &quot;if&quot; is a good idea. But in those languages, they have the benefit of a clear syntax with a keyword, and it&#x27;s a single assignment+test operator, very unlikely to be an accident due to a typo, or to hide an accident.<p>In contrast, I think the Go snippet looks error prone because the actual condition is all the way off the right. The assignment is obvious and the intention to test it can be presumed when skimming the code. But because the test is way off the right, at a horizontal position which will vary in different code, and at the end of a long line with a compound statement, I think it will be easy when skimming code to fail to notice if the condition is wrong due to a typo.<p>So I&#x27;m surprised Uber recommends this one.
评论 #21231067 未加载