9 ms·
I repeatedly tell people that Go takes twice as long to write and half as long to debug. Unless you write perfect code on the first try, the trade off is probab
by inlined 7y ago
I repeatedly tell people that Go takes twice as long to write and half as long to debug. Unless you write perfect code on the first try, the trade off is probably worth it.
- sagichmal 7y agoThat feels about right, but missing the most important measure, IMO, which is it takes 10-100x less time to read and understand a new codebase.
- baby 7y agoI spent years as a consultant reading codebases in different languages. I can tell you that Golang win hands down for clarity of code and structure of projects (and perhaps second after Rust in terms of security. If only it had options<>...) So yeah, it's actually quite fast to dig in a Golang codebase. You notice that as a normal user when you find it faster to read the standard library vs reading the doc, or when you read an implementation instead of reading a spec/algorithm to learn about it. My guess is that gofmt is a huge factor in this, but also the fact that there's not a huge amount of built ins, anf that the standard library is pretty complete.
- nkozyra 7y ago> My guess is that gofmt is a huge factor in this It really is. My code looks like your code and the next person's code. Go is opinionated and strict and that makes reading other people's code so much easier
- thatswrong0 7y agoI wish gofmt would let you set a desired line length and break it for you.. prettier has me spoiled in that regard
- mcbits 7y agoIf a tool is going to enforce line length limits, I'd rather have it spit a warning/error than silently try to guess a good place to break the line automatically. Otherwise, an editor tool that soft-wraps long lines at the (often poorly) guessed location without touching the code would be better.
- thatswrong0 7y agoBut that’s the thing about prettier - it wraps exceptionally well because it actually parses the AST. I never think about how I space my JavaScript anymore because it always does it correctly.. it’s one less thing to get in my way when I code
- mcbits 7y agoThe number of options that prettier exposes (despite boasting about being "opinionated", i.e. disregarding the user's opinions) suggests that there are people with different aesthetics or accessibility needs who would not consider one style to be always correct. IMHO we're about 10 years overdue for committing a canonical representation of that AST to version control instead of treating a particular serialized visualization of it as the single source of truth (and spending countless hours debating which format is "good enough" for everyone in every situation).
- hacknat 7y agoYou can always set your defaults for your editor.
- erik_seaberg 7y agoExperts' code should be clearer and more concise than novices' code. If that's not true, there's no payoff for getting more proficient with the language, and it's not doing enough to help you.
- nkozyra 7y agoThis is about readability. There are many other attributes of code (idiomatic? design? efficiency?) that differentiate. But I should be able to grok anyone's code within reason.
- oftenwrong 7y agogolang is not primarily designed for experts "The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt." – Rob Pike
- pjmlp 7y agoIronic in a company that prouds itself of PhD hiring games.
- justinclift 7y agoPackages extensively using reflect + interfaces together can be a bit of a pain to work through. :/
- sagichmal 7y agoAbsolutely. But those are clear code smells. Any org with competent code review would flag them and kill them before they proliferated.
- jeremyjh 7y agoWould you consider k8s to be developed by a competent org? They have 2324 func declarations that take or return an interface{} on master right now.
- sagichmal 7y agoKubernetes, like Docker, is notoriously bad Go. The authors essentially transliterated Java.
- inlined 7y agoThis. It was really hard to enforce supplementary style across my team to match common conservatism in popular codebases (e.g. only return a single value or a value and bool/error. Don’t expose channels in APIs) when K8s so blatantly fails them.
- justinclift 7y agoHave you seen the internals of the Go http library? :)
- inlined 7y agoHave you seen the internals of the rand library? HTTP uses interfaces cleverly to detect optional interfaces. Today I found out that rand.Rand does a type check on every core method to see if it’s source is the hidden type for global methods.
- abtinf 7y agoGo is the only language where I look at the standard library source instead of google whenever I run into an ambiguity in the docs. I think there are three reasons for this. First, the docs link to the actual line in source, so it’s just a click away and available in the exact context I need it. Second, I know I’ll be able to understand it: there are usually very few dependencies, so I can usually get all the context I need from a single file; the source formatting is familiar; code style, like variable names, are familiar because of the cultural influence of the Tour of Go; and there is usually no magic anywhere—I know that things are exactly what they appear to be, like when I see a variable declaration, it is not secretly calling a complex function (this is vital to human knowledge and is aligned with Objectivist epistemology’s “law if identity”). Third, every time I look at the standard library source, I become a better programmer. I’ve lost track of the number of times I’ve thought to myself “oh, that’s a clean way to organize this kind of code!” I often end up immediately using what I learn from the stand library source.
- bmurphy1976 7y agoI agree, and if others disagree they should comment and explain why instead of downvoting you. One of Go's major selling points (for me anyway) was a solid standard library written mostly in conventional Go style. It's a great example of how Go code should be written, and a wonderful learning tool for the language. It also makes participating in the community easier because that's one less thing you have to learn in order to contribute.
- unixsheikh 7y agoExactly.
- millstone 7y agoDisagree hard! a = append(a[:i], a[i+1:]...) That’s the recommended implementation of erase(). After this, is the original object referred to by ‘a’ modified? How can you tell? Let’s pop from a stack: x, a = a[len(a)-1], a[:len(a)-1] Did you read that 100x faster than ‘a.pop()’? Now this: a = append(a[:i], append(make([]T, j), a[i:]...)...) This is an operation called “expand.” What does it do? It is an honest question, I have no idea. These are completely idiomatic examples taken from the Go wiki. They are not readable.
- sagichmal 7y agoSlice operations are deliberately verbose in this way so as not to hide the cost of allocation that goes along with them. They are not common in code, but they do make good strawmen when you want to counter general points with specific ones.
- meddlepal 7y agoI don't think myself or any other Go devs I have worked with have once thought about allocation cost when using slice operations. This may be something super common for C/C++ devs but the big adopters of Go are Python and Java converts where we just don't pay attention to this stuff and after a decade or more of writing this kind of code were not going to suddenly start thinking in terms of memory allocation cost. I think this is one of those mistakes in the language that exist because early-on Go could have been a true systems language but it's been adopted by a large number of devs more as an infra and high-level automation language where correctness is more important than performance.
- edflsafoiewq 7y agoSlice operations are verbose because abstracting over them requires generics. Generic operations which don't allocate, like pop, are just as verbose as generic operations which do, while operations on slices of a specific type can be made non-verbose because it is possible to abstract over those. There is no principle of "deliberate verbosity so as not to hide the cost of allocation".
- inlined 7y ago
- meddlepal 7y agoToday I spent two hours tracking down why a nil pointer was occurring in my code. Turns out I forgot to pass it along to the struct initializer through one of the damn factory functions I need to create so I can hide internal fields properly... this was nested code in a framework. Tell me again how easy it is to debug Go. In other languages the compiler can just tell me in _seconds_ that I done fucked up. If you response includes "You're doing it wrong if you have deeply nested framework code" then you can rightly fuck right off too.
- sagichmal 7y agoWhy are you using factory functions? Why are you trying to hide internal fields? The description of what you have to do is setting off some warning bells. It's certainly possible to write difficult-to-maintain code in any language. > If you response includes "You're doing it wrong if you have deeply nested framework code" then you can rightly fuck right off too. I mean, can you point me to an example? Absent more context, I'm pretty confident that you're indeed doing at least something wrong...
- meddlepal 7y agoBecause we don't want to export internal fields of structures in our API or we need to perform initialization logic before considering the structure ready for use? That's a pretty common use case but ignore that for a moment and just distill the problem down to it is possible to have null pointer issues in Go code. Another example eith sufficient use of goroutines and channels it gets really tricky to debug something when a receiving channel blocks because something isn't sending. There's plenty more. I don't find Go any simpler to debug than Java, Kotlin, Rust, or Python and in many cases it is significantly more difficult because you're constantly fighting the type system or working through huge amounts of boilerplate.
- repolfx 7y agoTwice as long and half as long as what? I often get the feeling that Go users are implicitly comparing it to languages like Python or JavaScript. I've watched a client try to debug a Go codebase they had. It was sad. Their web server just returned 500 Internal Error and they tried to track down why from logs, but by the time the error had made it back up to the serving loop most information about where it came from had been lost. I suggested they attach a debugger to a server to see what's happening, they said debuggers don't work that great in Go and so people don't use them much. If they'd been using exceptions they'd have a stack trace and could have pinpointed the source of the fault in seconds.