33 ms·
Best practices for a new Go developer
- stonewhite 11y agoI was expecting an empty page with a huge "don't" in it. But instead there was interview excerpts from Go developers and a ambiguous list of "best practices".It would be more meaningful if this was backed with some actual practices with some code examples. I just don't see what people think others would understand by teleologic statements like: "write Go the way it wants to be written"
- Kiro 11y ago> I was expecting an empty page with a huge "don't" in it. Why?
- signa11 11y ago> I just don't see what people think others would understand by teleologic statements like: "write Go the way it wants to be written" well, this is a very general advice, approx. implying : "don't force your previous language's world view while programming in Go". f.e. if you are coming to Go from say Java, where everything is a class and where hierarchies abound, when you try to write a 'javaesque' go, you would be fighting against the language. however, embracing a 'goesque' worldview of composition+interfaces as primary vehicle for program design, would/should make the overall experience quite a pleasant one.
- rakoo 11y ago> I just don't see what people think others would understand by teleologic statements like: "write Go the way it wants to be written" To me it means "Read what the creators thought about when creating Go and how they view it, and do the same". But really that applies to any craft that exists: instead of trying to apply and adapt what you already know, clean your mind and start from scratch.
- lhc- 11y agoWait, the advice is "ignore your past knowledge and experience and start from nothing" ? That strikes me as terrible advice.
- signa11 11y ago> Wait, the advice is "ignore your past knowledge and experience and start from nothing" ? That strikes me as terrible advice. well, with knowledge i hope there is wisdom as well to apply it in a manner befitting the context.
- rakoo 11y agoMore like "Don't try to shoehorn your existing knowledge into that thing you are trying to learn and use; it may or may not fit but isn't supposed to". That absolutely doesn't prevent you to use your knowledge as stepping stones to understand the new thing.
- peteretep 11y ago> You will realize eventually that what you first thought > was worth criticizing was actually a deep work of > genius. Funny, I found the more I used it the less I liked it. > I’ve seen a lot of criticism of Go’s “shortcomings” > from people who are true experts in many languages > other than Go. Cool, normally I just call those people "experts". > I can’t recall similar criticism from someone who’s > worked with Go at a very deep level for a year or two. You would do well to understand the meaning of the term "survivorship bias".
- Kiro 11y agoWhat's with the condescending tone?
- jasode 11y agoCan't speak for peteretep but here's my guess... If you look at the quotes peteretep pasted, those "I-have-wisdom-that-you-don't" type of remarks can be interpreted as condescension. Therefore, it's human nature to respond to condescension with more condescension. To be clear, the blog author (Satish Talim) didn't write those quotes -- he's quoting Baron Schwartz.
- colin_jack 11y agoThe quote he was commenting on had a very condescending tone too: " Do not complain about something you think is missing, wrong, or stupid. You are ignorant and new to the language, no matter how much of an expert you are on programming in general."
- wiremine 11y agoI actually think it's pretty good advice. If you haven't used a language [1] before, park the opinion and get to work learning it. [1] or database or framework or whatever...
- colin_jack 11y ago
- drakenot 11y agoI was hoping this article would have more substantive advice for new Go developers. It seemed to mostly have very general advice that applies to most other languages like: "Don't try and write language X in language Y. Keep complexity down by not over using complex language features." I'm writing my current hobby project, a podcast fetcher, as my first project in Go. The project has been going generally well but there have been a few annoyances so far: * Why are you not able to easily version git dependencies? Go's solution to this problem is to tell you to create an entirely new git repository for each major version. Really? If they didn't want to go full blown dependency versioning with something like CocoaPods, they could at least let you specify a git branch or tag. * The db.Sql abstraction does not support multiple result sets. Therefore database drivers, like the popular mysql driver, don't support multiple result sets. This really limits the kinds of stored procedures you can call. * The debugger support is bad. I have to fall back to using print statements for most of my debugging.
- threeseed 11y ago"You can make it work, but there is a reason why the Go team chose not to implement that. And, no, it’s not that they are lazy." One of the many wonderful comments in there. Those annoyances you listed aren't Go's fault. It's yours.
- robryk 11y ago> Why are you not able to easily version git dependencies? Go's solution to this problem is to tell you to create an entirely new git repository for each major version. Really? If they didn't want to go full blown dependency versioning with something like CocoaPods, they could at least let you specify a git branch or tag. Take a look at gopkg.in[1]. This is a service that makes branches in other repositories go-gettable. Eg. go getting gopkg.in/foo/bar/v5 will download branch v5 from github.com/foo/bar. This seems to me to be a way of dealing reasonaly well with the issue -- the go get tool itself doesn't need to understand anything at all here. [1] http://labix.org/gopkg.in http://labix.org/gopkg.in
- gcv 11y agoA nasty workaround for a problem which should not exist in the first place. Ditto dependencies on private repositories.
- deleted 11y ago[deleted]
- oconnor663 11y ago> Because Go gives us interfaces and closures we can write much more elegant, generic APIs with a flavor similar to Ruby or Lisp and this is the direction the language naturally wants us to take. Personally I like to use the empty interface for plumbing and only pin things down to specific interfaces or concrete types where I need to for performance or correctness. That's a lot like using opaque pointers in C. What is it about Go that makes people assume it's shortcomings are beautiful designs? I learned yesterday that `x == nil` can return false even if x is nil so long as x is an interface type. But it depends on whether x is actually nil or a nil value with a specific type. (╯°□°)╯︵ ┻━┻ My other pet peeve is that a method with a non-pointer receiver that tries to modify the receiver object will silently drop those modifications on the ground, because the object is copied. Which makes some sense, except that Go likes to convert to pointer receivers automatically, so the caller can't tell that anything is wrong. The only difference is one character in the method definition. Everyone I know hits this bug at some point and loses half an hour before they learn to look for it. You could almost say "all method receivers must be pointers" except that you need to refer to interface types without the pointer. (╯°□°)╯︵ ┻━┻
- Strom 11y agoEverything in Go is passed by value (i.e. copied), even the pointers. The sooner you will understand this, the less problems you will have.
- oconnor663 11y agoThe part that confuses me is that a lot of pointers are taken implicitly. Method receivers depend on the method definition, and maps (and interfaces?) are always pointers. So it can be hard for me to tell the difference between pass-by-value and pass-pointer-by-value.
- falcolas 11y agoThe confusing thing is that those copies are wrapped in interface wrapper types when passed into a function which uses interfaces in its function signature.
- 11y ago
- jheriko 11y agoits not all go specific, despite the comment about 'C style' heap allocation and pointer usage, you will find your C code will get better if you do not do this as well. the heap is a last resort, not the first.
- scott_s 11y agoI found that comment strange as well - I consider "put everything on the heap" to be more of the default attitude in dynamic languages (Python, Ruby) and in the statically typed managed languages (Java, C#). In C and C++, I default to the stack, and I don't think I'm alone.
- adrusi 11y agoYeah, that was odd, I wonder if it was some kind of elaborate typo. Heap allocation is much worse in C than in Go because you're responsible for freeing everything you heap allocate. There are only a few good reasons to heap allocate in C: You're writing a library and want to be able to add fields to your data structures without breaking ABI compatibility. You need to return dynamically sized chunk of data, whose length can't be known to the caller ahead of time, like a string. Still consider returning it by writing to a statically sized buffer passed as an argument, piecewise, as in read(). You need a growable buffer. Still consider allocating a reasonable maximum sized buffer and BOUNDS CHECKING. Some library requires you to dynamically allocate to use its API. Oh well. You want to maintain API consistency and that requires dynamically allocating something that doesn't strictly need to be. Don't be dogmatic, but stack allocation, and occaisionally static allocation are much more maintainable than dynamic allocation.
- kasey_junk 11y ago> I resisted the recommended workspace configuration, as described in How to Write Go Code. Don’t bother, especially in the beginning I've had the same dev folder structure across platforms, languages, jobs and decades. I basically had to abandon that structure when starting Go. I fought & fought and at the end of the day it is just easier to use their expected workflow. It was (is?) galling but it was the only way to stop fighting the tools and get work done.
- XorNot 11y agoThe intellij go plugin is your friend. Per project go-paths. It's also a good use of make.
- jerrac 11y agoSo, if Go is as bad as the comments so far make it out to be, what are some alternative languages? Specifically, a compiled language that can be deployed without worrying about dependencies. That's the feature that has had me looking into learning Go. I want to be able to just copy one file to my server and run it, no need to install anything extra on the server to make my program work. Actually, can Go even do that? I think it can...
- kasey_junk 11y agoYou mean any compiled language with static linking? Don't they all support that? I mean you can even get the jvm/java apps bundled as a single binary if you really want to.
- stonewhite 11y agoStatically linked binaries is not a new thing. You can do that on many languages.
- chadaustin 11y agoHaskell is my preferred statically-compiled-but-with-coroutines-and-channels language. It's harder to learn and the tooling is not as good as Go's, but its type system is far more powerful and useful. You can build useful generic abstractions over all types of channels and use them in every context. In Go you either have to use interface{} and pay the perf hit or write a code generator.
- jerf 11y ago"So, if Go is as bad as the comments so far make it out to be, what are some alternative languages?" While a good question anyhow, it's not as bad as the comments make it out to be. Anything can be made to look bad by only looking at the negatives, anything can be made to look good by only looking at the positives. And the balance shifts depending on what sort of application you're writing. There's a reason that Go has seen a lot of success writing network servers. There's a reason why Go has no penetration into the scientific computing community, and I tend to warn away anybody even thinking about it. In particular, a lot of the people screaming about Go do not consider some of the positives. For instance, thanks to the implicit satisfaction of interfaces, I find it one of the easiest mainstream imperative languages to still create a separation between IO and pure code, by wrapping all IO behind an interfaced object, one that I may not even have to create (i.e., Files already implement io.Reader and io.Writer, io.Reader & io.Writer also already have several test implementations available in the stdlib and it's easy to adapt them to a few more), which then allows me to write some really good testing code, almost as good as Haskell. (In fact, swapping in alternate implementations is probably easier than in Haskell.) This can be done in other languages, but it often involves jumping through hoops to create your own objects that mirror other object's methods so they can implement an interface or something; in Go it's trivially easy. Between that and the way errors are handled, I find it relatively easy to write very bullet-proof code. And while I also consider it annoying that Go lacks half of generics (interfaces are actually half of generics, but it's missing generic types), there are also often ways of spelling your APIs so it matters less. My code actually doesn't end up with very many interface{}s in it, and many of the ones that do are "real", in that the code in question really doesn't care what's there. If you don't put those positives onto the balance, you don't get a proper view. It doesn't help that, frankly, this was not a very good article and I strongly agree it has tone issues. This brought out a lot of people who might otherwise have just clicked over without commenting.
- danieldk 11y agoLearn about stack versus heap, and recognize that Go treats the stack differently from other languages. Note that the Go language spec does not even contain the terms 'stack' and 'heap. Whether something is stack or heap-allocated isn't always clear. E.g. consider: foo := &Foo{} // or: new(Foo) This could be stack or heap-allocated (in the most popular Go implementation) depending on whether the compiler thinks it escapes or not.
- pcwalton 11y ago> Learn about stack versus heap, and recognize that Go treats the stack differently from other languages. Yeah, this comment strikes me as deeply confused. Go does not give you precise control over what goes on the stack versus the heap: it's even in the FAQ. There's a common misconception that stack vs. heap and value types vs. reference types represent the same distinction; they do not. For example, note that it is possible in unmanaged languages to have dangling references into the stack.
- masklinn 11y agoUnless I'm mistaken it is technically true though, AFAIK other languages fall in two broad groups * heap-based languages (vast majority of the high-level ones), everything is treated as heap-allocated, may be stack-allocated as an optimisation (while ensuring/conserving heap semantics)[0] * stack/heap languages, strict semantic separation between heap allocation and stack allocation, the developer decides whether values get heap-allocated or stack-allocated Go has the semantics separation of the latter (whether something is heap-allocated or stack-allocated had strong semantic significance and is not dependent on the thing's type) but the control of the former (the runtime decides and doesn't tell you) [0] a subset of these languages may have "value types" which have stack allocation semantics, that's linked to the type itself and the semantics are stable
- pcwalton 11y agoTo use your set of categories, Go is a fully heap-based language. Everything is semantically on the heap. Stack allocation semantics have to do with when the object is destroyed, which Go does not have any way to control in the language. Value vs. reference types are totally orthogonal. To see how this is true, try creating a value type (such as a struct or an array) in Go and capture a reference to it in an (escaping) closure to defeat the escape analysis optimization. The object will definitely be allocated on the heap.
- forgotAgain 11y agoI take it these are the idiomatic best practices.
- johnnydoebk 11y agoI'm not interested in C++, not using it, do not care about it. So, I am neither visiting HN links that are about C++ nor taking part in discussions related to C++. And I'm really curious what drives people in this thread that are coming to say they do not want to use Go, do not like it, and stuff like that?
- wyager 11y ago>And I'm really curious what drives people in this thread that are coming to say they do not want to use Go, do not like it, and stuff like that? Last year I wrote this article about why I didn't like Go very much. It was pretty well received here on HN, which is hopefully indicative of it being a good explanation. http://yager.io/programming/go.html http://yager.io/programming/go.html
- tunesmith 11y agoProbably because of the relative evangelism levels. I don't see many threads on hacker news talking up the virtues of C++.
- lobster_johnson 11y agoGo's surge in popularity — and with it, the surge of evangelism — compels people to take a stand, for better or worse. (If Go weren't popular, nobody would bother.) I suspect it's also partly due to Go's curious mix of maturity and immaturity, in an overall promising package with lots of momentum. Here's a young language that on the one hand is productive to work with and simple to understand, yet so obstinately awkward and inelegant in several other respects, and represented by a team of designers who aren't always saying what many want to hear. It's clear that Go was, first and foremost, designed for Google and their need for a natively-compiled, concurrent language that steers the user to a very specific path, largely defined by limitations. Its approach prevents language-theoretic cleverness that can complicate a codebase (think Boost or the STL), and it prevents a lot of foot-shooting and optimistic overdesign that newbies are prone to. But while that's wonderful for Google, that's also a frustrating to developers who don't need this invisible hand hobbling them, and sees Go's potential subverted by the stringent design principles. I admit I'm one of those frustrated by Go's type system, for example, or its heavy-handed approach to error handling. Part of the frustration is the lack of a clear alternative: Nimrod doesn't have the mindshare, Rust is overly complex and slow to compile, Elixir doesn't have the performance, C++ is, well, C++. Go, for better or worse, fills a kind of sweet spot that, unfortunately, also has a dash of sour. And that kind of frustration easily leads to debate whenever Go comes up.