Mat Ryer
medium.com/@matryer · Personal blog · on HN since 2015
Mat Ryer, a Go developer and author, writes about Go code style, HTTP services, open source projects and APIs.
What HN saysHN commenters cite his talk and posts on writing Go HTTP services and his code style, which they debate on mutation and branching.
23HN people shared it
10linked it in comments
27stories submitted
188story points
1 year agolast shared
2015people per year2026
Most-shared posts
- 1Go code: Line of sight principle9 people · 12 points · first shared 2016 · 1 comments on HN
- 2Show HN: Silk – Markdown driven API tests4 people · 14 points · first shared 2016 · discussion on HN
- 3How I write Go HTTP services after seven years3 people · 27 points · first shared 2018 · 2 comments on HN
- 4When your old open-source project unexpectedly gets to the top of Hacker News3 people · 9 points · first shared 2016 · 1 comments on HN
- 5I was offered $1M for my Go package – and I said No2 people · 7 points · first shared 2016 · 1 comments on HN
- 6The http.HandlerFunc wrapper technique in #golang2 people · 6 points · first shared 2015 · discussion on HN
- 7Vice: Go channels across many machines1 people · 82 points · first shared 2017 · 14 comments on HN
- 8Machine learning APIs are too expensive1 people · 9 points · first shared 2018 · discussion on HN
- 9Show HN: Cloud storage abstraction package for Go1 people · 9 points · first shared 2016 · 1 comments on HN
- 10Context has arrived: Per-request state in Go 1.71 people · 3 points · first shared 2016 · discussion on HN
- 11Use Machine Learning to help tech pr*cks communicate better ;)1 people · 2 points · first shared 2018 · 1 comments on HN
- 12Show HN: Moq – Easily mock interfaces in Go1 people · 2 points · first shared 2016 · discussion on HN
- 13Why you should introduce a cool-down period in your team1 people · 2 points · first shared 2017 · discussion on HN
- 14Calling Go from Swift1 people · 1 points · first shared 2022 · discussion on HN
- 15Protect Identities by Anonymising Images with Go and Machine Box1 people · 1 points · first shared 2017 · discussion on HN
What HN people wrote when they linked it
thinkingkong · 2021-01-17
The stdlib is the best for clarity. But there are some excellent examples of how to structure projects depending on what you're trying to build. Mat Ryer gave an excellent talk on writing HTTP Services. If you want a good example on how to write distributed systems then Hashicorps' projects are more or less gorgeous.
https://medium.com/@matryer/how-i-write-go-http-services-after-seven-y…
https://github.com/hashicorp
jonahx · 2023-09-15
Some important context re: my style...
> Any code anywhere in the function can mutate any of the variables
Regardless of the language I'm using, I never mutate values. Counters in loops or some other hyper-local variables (for performance) might be the inconsequential exceptions to this rule.
> More functions help scopes stay small, and data flow is more explicit.
Just write your big function with local scope sections, if needed (another local exception to the rule above). Eg, in JS:
let sectionReturnVal
{
// stuff that sets sectionReturnVal
}
or even use IIFE to return the value and then you can use a const. "A function, you're cheating!" you might say, but my goal is not to avoid a particular language construct, but to maintain locality, and avoid unnecessary names and jumping around.
> A side benefit is that "more functions" helps keep indentation down.
This is important and I maintain it.
See "Align the happy path to the left" (https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea88)
It is also worth noting that solving this problem with function extraction can often be a merely aesthetic improvement. That is, you will still need to keep hold the surrounding context (if not the state) in your head when reading the function to understand the whole picture, and the extraction makes that harder.
Using early returns correctly, by contrast, can actually alleviate working memory issues, since you can dismiss everything above as "handling…
unscaled · 2021-10-04
The section that you're linking to in Effective Go does not state anywhere that "branches are clunky, they are so intentionally to make the points where your code branches much more obvious".
It only promotes the concept that of using guard-clause style ifs that return an error and have no else clause, gradually eliminating each possible error condition.
This style of programming was later termed in the Go community "Aligning the happy path to the left"[1][2]
[1] https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea88
[2] https://maelvls.dev/go-happy-line-of-sight/
I wholeheartedly agree that this style makes code more readable and I have adopted it - and encouraged others to adopt it - in other languages besides Go. This style would stil be followed with the try or check/handle proposals. For instance, let's take the example:
f, err := os.Open(name)
if err != nil {
return err
}
d, err := f.Stat()
if err != nil {
f.Close()
return err
}
codeUsing(f, d)
f.Close()
return nil
With the simple try proposal that would be:
f := try(os.Open(name))
defer f.Close()
d := try(f.Stat())
codeUsing(f, d)
With OP's variant of the try proposal, using a question mark this is arguably even more readable (less noisy):
f := os.Open(name)?
defer f.Close()
d := f.Stat()?
codeUsing(f, d)
As you can see, these proposal reduce - not increase - nesting, so they are completely in line with what Effective Go is saying.
kminehart · 2017-09-22
I worry that a lot of developers who have been using languages like Java or C# see Go and immediately feel the need to point out that Go doesn't support language features that they've come to rely on, and so they see that as a weakness or a flaw.
With Go, you're getting a lot of high-level language features like anonymous functions, while also gaining the control that you're not able to get in higher level languages like Python or Ruby or Java.
I think this works out great for cloud computing, where performance is a major requirement, but the technology is expanding rapidly enough that a step up from C or C++ is very necessary.
A lot of the complaints I hear are related to abstractions, too, and I understand those to an extent. I also think that if you're complaining about the lack of generics, maybe you're not thinking about interfaces correctly. A perfect example is the beautiful simplicity that is the [`io.Reader`](https://medium.com/@matryer/golang-advent-calendar-day-seventeen-io-re…
So, whenever someone says something like the OP:
> As a simple language to wire pieces together, Golang is fine, but it really doesn't give you the tools (imo) to be productive for anything more complex than simple apps.
I take that as meaning, "I've never seriously used Go beyond writing a hello world app. It doesn't have the features I rely on to be productive, therefore I don't think it's a capable language for larger projects."
I will say though,…
DonHopkins · 2020-02-17
Good linters correctly highlight all missing semicolons as a symptom of sloppy, negligent, careless programming (or pointless syntactic showboating). It's also technically syntactically valid to omit braces around single statements after if, else, for, and while statements, but idiotic and dangerous to do that, too.
https://wiki.c2.com/?FixBrokenWindows
https://www.rtuin.nl/2012/08/software-development-and-the-broken-windo…
https://blog.codinghorror.com/the-broken-window-theory/
https://medium.com/@matryer/broken-windows-theory-why-code-quality-and…
kaizendad · 2019-02-22
This is exactly correct. The cost of holding the entire object in memory, for any significantly complex statement, is going to add up quick if you're dealing with large numbers of users/pageviews/etc. The cost of pre-calculating everything in the object for any complex math similarly gets large when you're dealing with something large-scale. Early returns matter a lot with scale, and make [code line of sight](https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea88) much clearer -- which matters a lot of if your team scale is larger, as in many companies that might have multiple teams working on one shared codebase.
ahussain · 2018-09-10
I quite like this short piece as a way to explain why things like exiting early and not nesting loops are important: https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea88
mplewis · 2017-03-07
Yep! That's happy path/golden path/line of sight programming, and it's awesome.
https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea88#.m3qqyv…
nindalf · 2015-04-27
I think you ought to reconsider what the other guy said. His suggestions were quite good because they lead to simple, idiomatic code that relies solely on the standard library.
You can read more here - https://medium.com/@matryer/the-http-handlerfunc-wrapper-technique-in-…
Cthulhu_ · 2019-07-04
> error check has == instead of !=
And you return the error as-is if its nil; seems fine to me?
Your second example is also a bit... far-fetched because it tries to be smart by putting the error checking in the same line. There's also the "line of sight" guideline which states that the happy path should be left-aligned, while edge cases - like errors - should be in indentation [0]. See also the law of least astonishment [1], which your final example does not conform to.
Yes it will compile and yes it is an issue but that's not because of the language. It's because of an attempt at cleverness by writing more compact, of having the happy path in an if, and (arguably) by reusing variable names - but this seems pretty common, and longer variable names like idk, `osOpenError` and `fileStatError` seem to be discouraged in favor of reuse.
So I'm not sure if you're getting your point across like this.
[0] https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea88
[1] https://en.wikipedia.org/wiki/Principle_of_least_astonishment