Live data from Hacker News

Uber Go Style Guide

github.com

81–90 of 140 posts

Re: Uber Go Style Guide

#81
post #10

Pretty good. Some opinions that fall under "be consistent within our code base" (which is why Uber should have a style guide at all), so all good. Just one comment though: > Embedding sync.Mutex Never do this on an exported type. If you embed sync.Mutex that makes "Lock" and "Unlock" part of your exported interface. Now the caller of your API doesn't know if they are supposed to call Lock/Unlock, or if this is a pure…

> Never do this on an exported type. If you embed sync.Mutex that makes "Lock" and "Unlock" part of your exported interface. Now the caller of your API doesn't know if they are supposed to call Lock/Unlock, or if this is a pure internal implementation detail. Isn't that exactly what they say? > Embed for private types or types that need to implement the Mutex interface. Personally, I would never embed a sync.Mutex th…

Curious. Under "Returning Slices and Maps" they use it in their "Good" example.

Re: Uber Go Style Guide

#82
post #22

Earlier quoted context omitted.

Uber have well over 1,500 microservices written in Go, it is the primary language backend services are written in at Uber.

> Uber have well over 1,500 microservices written in Go 1500 ?! I can't even imagine how micro a microservice could be such that Uber could have so many. edit: Having said that, the Monzo blog post also on the front page says it has 1100 microservices, so I suppose I've just not worked somewhere with 'actual' microservices. What constitutes a 'service', a single procedure for RPC?

The must have a leftPad microservice.

Edit: eh, looks like I was not the only one who immediately thought of that :)

Re: Uber Go Style Guide

#83
Copy Slices and Maps at Boundaries: https://github.com/uber-go/guide/blob/master/style.md#copy-s...

The suggested good clone is not very efficient: https://github.com/go101/go101/wiki/How-to-efficiently-clone...

In fact, I prefer the suggested bad one instead. We should let the caller to determine whether or not a clone is needed.

--------------------------

Start Enums at One: https://github.com/uber-go/guide/blob/master/style.md#start-... 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.)

--------------------------

Local Variable Declarations: https://github.com/uber-go/guide/blob/master/style.md#local-...

Personally, I prefer "var x = ..." 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.

--------------------------

Avoid Naked Parameters: https://github.com/uber-go/guide/blob/master/style.md#avoid-...

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.

If this must be done, I recommend to define and use some named bool constants instead.

Re: Uber Go Style Guide

#84

Earlier quoted context omitted.

Yes, that's not good, but it seems like in practice this doesn't come up too often in Go? More typically you're building a new slice containing the results of a query or other computation, and returning it without keeping a reference. Or instead of exposing an internal map, you have a Get method.

I have found this to be true of everything other than byte slices, where the result is some of the worst bugs I've had the displeasure of tracking down. Many Go libraries like to offer passing a byte slice to reuse as a destination. Many Go libraries take byte slices or structs containing them as arguments. A common result is "loop over some input, read it into the reusable slice, pass the slice to the next step". It…

Ouch. I guess this would be a reason to use strings more, since they're immutable.

Re: Uber Go Style Guide

#85

Earlier quoted context omitted.

I have found this to be true of everything other than byte slices, where the result is some of the worst bugs I've had the displeasure of tracking down. Many Go libraries like to offer passing a byte slice to reuse as a destination. Many Go libraries take byte slices or structs containing them as arguments. A common result is "loop over some input, read it into the reusable slice, pass the slice to the next step". It…

Ouch. I guess this would be a reason to use strings more, since they're immutable.

Using string doesn't allow reuse, so you are leaving significant performance on the table.

Re: Uber Go Style Guide

#86
post #55
post #53

Earlier quoted context omitted.

It could be, if the Rust borrow checker were a Go tool that would solve this problem. In reality it's part of a different language which exposes a lot of complexity to the programmer as opposed to Go, which religiously avoids that.

No, the point of this observation is that Go exposes this complexity, it just doesn't make it explicit.

I think this is where Rob Pike got it backwards (in terms of one of his stated goal for Go).

Go is a very effective tool in the hands of experienced programmers, without having to pay the cognitive load price of 'Mommy' languages. I am reminded of Bryan Cantrill's rant regarding threads in this context.

Writing solid software is hard. It takes skill, experience, and serious battle scars. Tools and languages can help, but at the end of the day, it comes down to the team that writes the code.

Re: Uber Go Style Guide

#87
post #83

Copy Slices and Maps at Boundaries: https://github.com/uber-go/guide/blob/master/style.md#copy-s... The suggested good clone is not very efficient: https://github.com/go101/go101/wiki/How-to-efficiently-clone... In fact, I prefer the suggested bad one instead. We should let the caller to determine whether or not a clone is needed. -------------------------- Start Enums at One: https://github.com/uber-go/guide/blob/ma…

Re: Start Enums at One. As explained, it is to avoid making the first enum value the default when making it the default is not appropriate.

Re: Uber Go Style Guide

#88
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.

Re: Uber Go Style Guide

#89

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 thi…

Maybe to avoid deadlocks?

Re: Uber Go Style Guide

#90

I really like the horizontal 'Good/Bad' code comparisons in this guide. I didn't realize how horizontal vs. vertical code comparison affects readability; IMO horizontal is MUCH more readable. Example: https://github.com/uber-go/guide/blob/master/style.md#defer-...

+1. It is quite an achievement by Go as a language and/or community to have generally short lines of code where two columns fit in a regular website width. I don't like everything about Go, but it's usually pretty easy on the eyes for this reason.
Post reply on HN