6 ms·
What a delight to read, even as somebody who has barely used Go. I really appreciate the author's self-awareness as demonstrated in things like "Expected proble
by wpietri 5y ago
What a delight to read, even as somebody who has barely used Go. I really appreciate the author's self-awareness as demonstrated in things like "Expected problems that weren’t".
The bits about exceptions and typing remind me of an open question I have about Go: to me it mainly looks like a language for well-understood problems. Static typing and the lack of ability to do broad, high-level exception catching seem to me to be well-matched for problems where you already understand the solution pretty well. E.g., a port like this.
But how is it for poorly understood problems? E.g., You're doing a startup where the technical risks are low and the major unknowns are about user needs and the correct experiences to deliver. Or you're doing exploratory work for an art piece.
In those contexts, I've felt much more effective starting with vague/implicit typing and some broad, high-level exception-catching blocks. That lets me avoid a bunch of questions about the right types and structures until a more solid domain vocabulary emerges. At that point you can refactor/rewrite toward clarity. But I don't see a good way to be willfully vague/casual in Go.
- whoisjohnkid 5y agoAll depends on what’s important to you in that startup context. If you need a good mix of high productivity and low costs on the server side I think go is a good fit. If you don’t care so much about costs and scale on the server side then something like Ruby on Rails might give you that extra productivity boost you need to verify the concept.
- wpietri 5y agoYeah, given how computers keep getting cheaper, I only start caring about low server costs once I have a demonstrated cost problem that's going to be material to the business model or to the budget. Until then I'm very happy to burn CPU time to accelerate developers. Who keep getting more expensive! And yes, the point of verifying the concept is key for me in this. Before product-market fit, I just don't have much confidence in any domain model. Once we have demonstrated that particular people are excited to pay for a particular thing, that changes. Then we can understand how those people think, and how we think about their behavior, such that we can do real domain-driven design. At that point I'm much more willing to lock down types.
- laumars 5y agoI’ve never once felt like strong typing has prevented me from solving unknown problems. I won’t deny that there have been occasions where I’ve had to redefine a type across a large code base and that has taken me half an hour to a hour. But I’d take that over type validation at run time. For me, having strict typing helps with unknown problems because it gives me greater confidence that refactoring wouldn’t introduce subtle regression bugs.
- wpietri 5y agoThanks for the reply. For me the cost isn't just redefining a type. It's the continuous work of reifying types that could be implicit for a while and possibly forever, because concepts don't last long enough to need it. For me, having written a lot of code in Java and Scala but also in Ruby and Python, typing is a nice adjunct to unit tests and operational monitoring, but not my fundamental way of ensuring correctness. And correctness often isn't the highest value in practice, especially early on in a startup's life.
- marcus_holmes 5y agoHonestly, you don't notice it once you get into the Go mindset. The exception handling looks onerous, and is a pain at the start. But it doesn't take long to get used to it, and then (for me anyway) it becomes second-nature. Everything returns an error, and you have to handle that error (even if only passing it up again). Static typing is more "fun" when you're exploring new concepts, but interfaces are the key. Defining the interface at the beginning ("what do I need this thing to do?") and then implementing it with a struct/whatever, feels like the right way to do this.
- oefrha 5y ago> But it doesn't take long to get used to it I did get used to it, but all the if err != nil { return nil, err } sometimes taking up half or more of the vertical space of a function is still an eyesore to me, even after writing a quite substantial amount of Go.
- ufmace 5y agoThis exactly. I haven't written enough Go to be really annoyed by the more subtle things in the post, but it'd really be nice if they could come up with some syntax sugar for that kind of like Rust's ? helper. Maybe the Go ? is allowed within any function whose last return value is an error on any function call whose last return value is also an error. Call it with ? at the end and accept all but the last return value. At runtime, if the err is not nil, then it returns from the function, supplying the err value and nil for any other return values.
- oefrha 5y agohttps://go.googlesource.com/proposal/+/master/design/go2draft-error-handling.md https://go.googlesource.com/proposal/+/master/design/go2draf... I don’t think it went anywhere, unless I missed it.
- preseinger 5y agoError handling being explicit isn't an eyesore. It lifts what is with exceptions a hidden control flow to the foreground.
- autarch 5y agoI feel like strong typing _helps_ when exploring a new domain, as it forces you to really think about the data you're operating on. In a language like Perl or Python, it's so easy to just throw around a bunch of hashes/dicts and that can get messy really quickly. I don't miss _exceptions_ in Go but after using Rust for a while I've come to really love Rust's `Option` and `Result` types. They're more ergonomic and expressive than Go's errors-as-values, and the use `Option` also eliminate `nil` entirely, which has been a regular source of runtime panics in every large Go codebase I've worked on.
- tialaramex 5y agoSum types are a thing I don't want to be without again. Not only the built in Option and Result, but once you're in the mindset you find they're the right fit for other problems too. In Rust itself, writing stuff where I actually care whether my structure is 16 or 20 bytes because I need to fit hundreds of millions of them into RAM, I like that Sum types ensure Option<NonZeroUsize> is the same size as usize, by reasoning that 0 isn't a valid NonZeroUsize and so it can signal None. However on a language like Go I don't miss that - what I do miss is the fact that in Rust I can't mistakenly end up with None(actually_something) or both an error and the result that shouldn't be there if there was an error.
- teddyh 5y agoPython is strongly typed, not weakly typed. What you are talking about is static typing, which Python is not; Python is dynamically typed. Please do not confuse the two concepts.
- kraig 5y agoWith generics around the corner I am really hoping we see some flavor of Option & Result coming to Go. But I won't hold my breath for ?.
- preseinger 5y ago> I won't hold my breath for ?. Good idea :) `?` hides a control flow that Go takes great pains to make explicit. Adding it to the language would be a disaster.