I really wish golang had more canonical content. But at this point, I feel like I'm working against the grain. Golang doesn't feel like a language that wants to prescribe a lot more than fundamentals. How you structure your code beyond the src/git/path/your-code/ is completely up to you and every repo you visit could be different. It's not my thing personally, and I'm leaving this comment just in case any "want to try golang" folk stop by. This is something you should be aware of going in. Don't bang your head when you can't find a clear way of doing something that probably seemed simple in other languages. Embrace the new concept and see if you can get used to it.
That said, if anyone ever breaks into the eco system with an es lint style tool that allows experts to share their best practices via plugins, that would be awesome. If that exists already, please do let me know. I'd love to give it a go.
This is an unusual criticism. Typically Go is faulted for being too opinionated, and it’s projects too predictable. In fact, this is why I took to the language—no need to see past every maintainer’s personal flourishes just to build the code or run the tests. No ceremoniously nested directory structure. No figuring out how to point the build tool to the source files or how to convince the build tool to output or run a test target. Everything is right there, rather plainly and consistently across all projects. This does mean I have less room for creativity which is an okay tradeoff for me because I have just enough creativity to spend on the application and its architecture and the rest should just work, but I recognize that some may disagree and that’s okay too.
1. I don't think powerful abstractions are often that useful. I use Python in my day job, and we mostly don't use many high level abstractions. We never use monads, for example, and while we do use async futures, these are strictly worse than Go's concurrency features.
2. Pretty sure abstraction power drives _less_ consistency, not more. Effectually, it means there are more ways to do the same thing (and more ways to screw it up and make a mess), and consistency depends on organization discipline and less on the rails of the language. I don't mean to say abstraction is bad--only that consistency is one of the costs, not an advantage.
I'm interested to hear your thoughts.
It depends, I think. Abstractions allow users to specify part of a program's behavior independently from others. This is not intended to start a flamewar or pick on Go, but for better or worse Go does not support user defined generic functions. One consequence is that certain kinds of methods are difficult to write in a generic, performant, and type-safe way. If users want performance and type safety, they need multiple implementations of those methods for each desired type. This leads to multiple copies of very similar code (which can evolve independently, lowering consistency) or the use of on of the community-driven code generators (which all have their own differences, again lowering consistency).
Adding generics could largely make all of this inconsistency go away, but as you point out would enable a whole slew of other programming patterns more ways to make a mess.
I prefer to think of abstraction techniques as shifting consistency. Ideally, they provide an obvious way to factor out one piece of a program's behavior, allowing developers to focus on the rest of the behavior independently.
Generally Go's abstractions are based on dynamic dispatch (virtual function calls) which are quite cheap and are the basis for most other languages' abstractions. There are languages like Rust and C++ which offer zero-cost abstractions and generally beat Go in performance and abstraction power, but lose in other ways. If you're comparing Go to Java, C#, Haskell, OCaml, Python, JS, and Ruby, Go performs on par or better.
As far as abstractive power, Go does quite well, although there is still some _boilerplate_ (for loops and closures); however, this is generally not where your bugs come from (certainly not your troublesome bugs) and boilerplate is consistent by definition. I think the biggest reason Go's lack of generics irks people is because they want _terse_ code, because terseness is the most obvious (but least useful) kind of DRYness. The next biggest reason is more legitimate--getting a lot of typesafe abstractive power out of Go requires a different bag of tricks (and a different way of thinking about abstraction) than languages with generics.
I think "powerful abstractions" fall into other categories, e.g. ORMs. While gORM kinda-sorta works in the context of golang limitations, it's missing a lot of stuff that doesn't currently fit into the go model.
> Typically Go is faulted for being too opinionated, and it’s projects too predictable
The parent addressed this. You are confusing inflexibility of language with inconsistency of ecosystem. Devs can want both more flexibility in the language, syntax, and type system and more commonly accepted project-level structures/approaches at the same time. I definitely don't see projects being too predictable at a general level as each lib has its own way of doing many things.
Why am I writing all this ceremony (comparatively little compared to other languages, but ceremony nonetheless) when the new, better way is coming?
Additionally, I agree that the idiomatic design patterns of go aren't well defined beyond "use channels, share memory by communicating, handle errors, and dont ever use functional precepts". A lot of go feels really good which makes the not as good parts really stand out.
Personally, I'd like to see small QoL improvements (beyond generics and error handling) like named arguments, native functional operators like map, reduce, filter that take advantage of go's great runtime, and something cool like kotlin's by keyword for delegating ( https://kotlinlang.org/docs/reference/delegation.html)
Whether or not the new way will be better is far from assured.
I'm outing myself as a bit of a "get off my lawn" greybeard here, but as long as such a large swathe of the industry remains trapped in a permanent state of convulsion where everyone competes to build the next monument to their own cleverness, the unprecedented consistency, clarity and productivity that vanilla Go 1 provides will remain under-appreciated.
There's an awful lot of sound and fury over generics and error handling. I sincerely hope that if and when something is done about it, it isn't done in a way that gives anyone a license to be clever.
> "use channels, share memory by communicating"
They walked back a bit from this, thankfully, and I'm seeing less and less nasty "channels for the sake of it" code these days as a result. The party line seems to be closer to "channels are good and bad, mutexes are good and bad, favour whichever is goodest" nowadays, and the larger projects I've worked on have typically been about 50/50 
I find there's a lot you have to do manually to handle them correctly and it's easy to miss details. I think they're best cordoned off behind isolated, encapsulated parts of a channel-free public interface.
To walk back a tiny bit from my earlier "80%" claim, I reckon channels are probably more like 50% complete. The existence of "context.Context", itself very much half-baked, is a symptom of that.
You have to think long and hard about cancellation and blocking every time you interact with them (even if you decide you don't ultimately need to), and the results, once you've (hopefully) handled all the corner cases can degenerate into a tangled mess that's hard to reason about, harder to test, and impossible to change. I like to call this kind of code "channel soup".
I'd be interested to see proposals for what the 80% version of channels would look like. What we have now is a great start, but it's not great yet.
Many people aren't using "decent text editors". vim isn't one. Webpages and prints of code chunks aren't. Information that you must inquire interactively is simply not the same as static information expressed inline in the code. Such is always a little more typing work but often it's worth it.
Everything old is new again.
There's a semi-recent experiment to try to make a pluggable lint system, but I'm not sure what the current status is.
For my workplace, tbh I plan on making something semi-hacky just to get us off the ground + use real go plugins so we actually have some minor extensibility without reams of boilerplate. I've built several tiny things that just use the AST (which is not bad at all, and quite fast - several thousand source files take about 250ms), and they've been worth the effort like 100x over, but it's hard / impossible to do anything better without the type checker + significant amounts of work.
: very highly recommended, it has far more / better checks than others I've seen, but is also quite slow and hard to extend: https://staticcheck.io/
: it's honestly quite a good repo, but there needs to be more. it's a fairly unfriendly API and there are few helper libs as far as I've seen: https://golang.org/s/types-tutorial
I've written a linter / code formatter / auto bug repair tool internally for my current company and it sucked. Still sucks. Comments doubly so.
The examples are few, undocumented, and don't always work with the vendor directory concept.
I had to write my own custom importer to get vendor support to be more reliable.
I like the concept of shipping with an AST package; it's very forward looking and useful.
I too hope the go/analysis package could be the answer. I believe it has not merged but has a prototype version that conflicts with master. Maybe they'll patch it up and get it landed soon. I hope, anyways
For manipulating code tho (e.g. for code gen or rewriting), yeah - absurdly unfriendly fits pretty well, and comments only kinda sorta mostly work until you actually try to produce anything polished. It kinda feels like they prioritized forward-compatibility at the cost of usability (which could be a decent decision / a fair tradeoff, but it sucks as a user trying to do stuff now).
Erm...I'm confused. Why on earth every repo should have the same structure? I mean, I understand when you use a framework that prescribes you a layout, but even so, good frameworks try not to get into developer's way. Why the source code of a webapp should have the same structure as a, say, database? There were quite a few comments about standard project layout - I'm sure there is something similar for every language, but these things are just recommendations. And thank god they are not rules. Am I missing something here?
When I open a Maven project, the Java sources are always (99,99% of the time) in src/main/java, the resources are in /src/main/resources, the Java test sources are in src/test/java, etc.
Every project has to have source code, every project could have resources. Every project could have test sources, etc.
WHY SHOULD ALL MY CODE SIT IN ONE FOLDER? I say gripe, it was a huge annoyance. Why on earth, also, should i need to use the repo path in my structure and imports? It's obscene.
My next annoyance was the utter inability to easily parse dynamic JSON. But you know what the JSON looks like? Great, you'll only have to wrap it in a few structs and check your capitalisation if you want it to parse at all, no problem you think before half a day has gone just parsing one response.
The vendoring makes my month painful as I'm retooling the build system for the flavour of the month vendoring toy.
Structuring large projects still causes me great pain.
All of that said, Golang is now my favourite language to program in, and is my default for any new project.
In particular, parsing JSON is a breeze, just like in Python. And there is no GOPATH weirdness.
Give Nim a try if you haven't already, it may just become your new favourite language :)
How does it compare to Rust, which is currently top of my list to learn next?
Can you suggest a reason, or a few why Nim should knock Rust from that spot?
I only follow Go casually ATM, but I think that it might fairer to say that the core team wants to stay focused on delivering the language and implementations, so we get blog posts and conference talks, but not a big trove of guidance on patterns & practices.
The best place to interact with the wider Go community is the Gophers Slack, and if you visit there, you will find that there's a lot of knowledge and thinking, but it's in scattered places. For example, this article will probably be cited in any discussion of application structure: https://medium.com/@benbjohnson/standard-package-layout-7cdb...
Have you seen gometalinter? Its defaults are way too computationally expensive for me, but it brings together reports from a lot of different linters.
I would be very wary of a language who has core features around such transient things than JSON unpacking.
We use Rails and React.
We tried Go for backend but Go is missing ActiveRecorss, payment gateway libraries, etc...
Where is migration management like sqlachemy or activ records?
For building SaaS product i think you should choose Rails.
It takes only few minutes to creare subscription billling, team accounts, invoice etc.. functionality.
I would like to know what you guys use.
To simplify a bit: Go is in the same bag as C++/C#/Java, Rails is in the same bag as PHP & [Symfony/Laravel].
If you're mass building CRUD web applications against customers requirements then, clearly, RoR is the best tool for the job (versus Golang).
Go is in the same bag as C++/C#/Java/Ruby/PHP (languages)
Rails is in the same bag as Symfony/Laravel (frameworks)
PHP is a language distinct from the other frameworks listed.
Small nitpick, but I always hate to see conflation of languages and frameworks when making comparisons.
I didn't have to fiddle with any paths or env vars in my scripts. It made my day easier. This is an example of something that seems like a good practice only after you've gotten some gray in your beard.
Why wouldn’t one want all of one’s code in a single place? What’s wrong with organisation? If one needs to work with different versions, then that’s what version control is for, isn’t it?
Obviously I’m missing something, because my opinion seems to be in the minority. I wonder if it’s because most people are using GUI file managers, which make using directories of code more difficult, while I use emacs and the shell, and so can comfortably manipulate files & directories at scale.
The short answer is to use git tags. You need to include the `v`, e.g. `v1.2.3`. If you don't use git, I don't know the answer.
But this is exactly what 'go mod' is NOT doing. It's called 'Minimal Version Selection'. Quoted right from the lead core dev's blog: ' For stable development, today's build list must also be tomorrow's build list.' (https://research.swtch.com/vgo-mvs).
From what I gathered, 'go mod' is the first mainstream tool which is going that way (but I would be glad to be proved wrong!). Other package manager are using lock files which have their caveats (see https://research.swtch.com/cargo-newest.html for an in depth examination of the revered cargo approach on low-fidelity builds).
I found that lib and tool documentations written by their authors tend be to be too long. It's understandable since they are passionate about the subject and want to talk about every details, but it's not great when you just want to quickly add a lib to your project or use some tool.
- I can see the datasheet where this micro has 32 message objects and a FIFO mode - but please tell me how you INTENDED it to be used because after weeks of figuring out the obscure memory and buffer system it turns out you never INTENDED a fifo rollover. Ok, that would have been excellent info on Day1.
- Your framework has a couple of examples and each function is documented. Great, but imagine my surprise when it turns out I can’t access a ‘global’ memory object outside of your function because you never intended that to happen - and never thought to let me know.
- This is the entire concept of a WHY comment vs a WHAT comment. Don’t write //increments X+1 instead use //counter ticked here because new value is used during the loop, must be placed at the top, uint8 / rolls at 256 for an x++ example. WHY comments made a big difference in the readability of my code. The goal is to relay intent.
The thing is, you don’t want to rigidly be stuck to someone else’s idea - but it’s extremely helpful to know how they planned for you use this because maybe the choices they made do make sense. Oh use an array of this memory type instead of casting it all to a class/structure! Yea, that’s fine and will be more efficient to search through etc etc.
I don’t need know why but engineers are really bad at telling you what they intended when making the product.
Maybe I’m just old fashioned, but to me this is a code smell. It reeks of needless coupling, and I suspect one day (sooner rather than later) the golang designers will come to regret it.
To top it off, despite being tied to a VCS, it seems to lack a useful means of enforcing versioned dependencies.
This simply does not look like a good design. Is this really the new and improved version? If so, how god awfully bad was the previous iteration?
go mod init mymodulename
This will download all the dependencies needed automatically.
You can also do this (from scratch as well):
go run main.go
And it will still download the dependencies.
If you use a modulename like github.com/dana321/test
you can include a subfolder of your project by importing github.com/dana321/test/mysubfolder for example
If you bring down the wrong version (ie. an older) version of a module, just edit the go.mod file and modify the version (after the space where the url is) and change it to master on the line where the module is. When you next run go build or go run it will re-download and re-populate the line(s) you've changed in go.mod with the latest version.
There really isn't much else you need to know!
This guide outlines the set of incantations required to accomplish that & frankly having fought through figuring it out myself from the doco, this would have saved me a bunch of time.
For Go modules if you don't have 'GO111MODULE' set to 'auto' or something appropriate, your code will whine about not being a module or something ridiculous. It will also cry about pulling in Go code with 'go get' if you don't have that environment variable properly configured.
If you don't set anything, and you are inside GOPATH, module mode is disabled. If you are outside GOPATH, module mode is enabled.
I think that is the most sane behavior. And this flag is needed because modules are an experimental feature.
How else do you recommend to release experimental features ?
I'm perfectly fine with not using them, but I've heard conflicting information about the future roadmap. If I have to use them later, I'd rather switch now, but if I don't have to switch even in 10 years from now, then I'd prefer not to switch to modules at all.
Does anyone know more about this?
Well, `go help modules` is a good combination of exhaustiveness and conciseness, IMHO.
The mod command does not vet any computed hashes of the dependencies found in your vendor directory.
Note the lack of conditions on that statement, up to and including the fact this statement isn't even about Go, nor is it even about open source! It is simply a fact. You own your dependencies and you need to support and audit them. You are free to support and audit them by not supporting them at all, not auditing them at all, and blindly pulling in whatever random mutations they may go through in the future. You own the consequences of such terrible support. You own the consequences of good support.
This would alleviate the need for your build to have a internet connection no?
I do like the new modules system so far though!
Being opinionated is about onboarding people with the best experience from the experts of the language, then let people overwrite or choose their own way of doing things when they know what they are doing.
I'm really not sure. Idiomatic Go is something well covered. Gofmt is ensuring consistent formatting. The official docs have an entry dedicated to this: https://golang.org/doc/effective_go.html.
And what would be an opinionated language if Golang is not?
I couldn't care less about formatting differences between repos. Ignoring superficial formatting difference, Ruby's community also has one package manager (bundler) and build tool (rake) with a widely followed naming convention and directory structure and community consensus set of libraries.
Both the above languages I can build a codebase I've never seen before and have it running within minutes even without README.
Go feels like the wild wild west. Everyone has their own directory structure, with different ways of fetching dependencies (modules vs dep), building (seems to have consolidated around go build vs make), with everything hand rolled or whatever NIH selection criteria they used for their libraries.
Yes, an 'official' package manager have clearly not been a target for the core team for a (way too) long time, whereas Rust has envisioned that 'community' part from the beginning.
> I couldn't care less about formatting differences between repos.
Whereas, to me, an official, no-question-asked tool like 'gofmt' is godsend. It really depends on what you're building and in which context.
> , building (seems to have consolidated around go build vs make)
Not sure here, 'go build' is clearly the idiomatic building way from almost day one.
> Both the above languages I can build a codebase I've never seen before and have it running within minutes even without README.
That was rather not (enough?) straightforward under %GOPATH% era, indeed. Today, with Go modules, its a one liner 'git pull; go build', granted you have Go 1.11 available in %PATH% and that the codebase already have a go.mod file (if not, a 'go mod init <pkgname>' should fix it).
Let me give you an example, it might be easier for me to explain it this way.
Writing a web application that responds to a post request. I am guessing I can use net/http library to achieve that. But does it implement CSRF prevention automatically, or should I be already informed about including it as a developer?
I would be grateful for letting me understand this part. I am not against the language, but just curious.
I think I get where you may come from. Indeed, Golang (the language and its standard lib) is not a framework-language toolkit ala RoR. The standard lib is providing building blocks with really straightforwards and clear documentation (check https://golang.org/pkg/net/http/#pkg-overview).
> or should I be already informed about including it as a developer?
I guess you really should, whatever language/framework you're currently using.
> what i have meant was mostly about the way an application is built with golang.
Yes, clearly the confusion may be here, I took it as "the language is not opinionated", whereas you were in fact saying that the language and its standard library are not a universal web application toolkit/framework.
In which cases should I adopt modules versus just sticking with $GOPATH?
‘go mod init vendored’?
> go get -u ./...
should probably be
> go mod tidy