Counterpoint, I wish there were more resources for new languages that assume you already know how to program.
Professional Javascript for Web Developers[1] is a favorite of mine, because it doesn't waste time teaching you to program and teaching you the language. Instead it points out things that will surprise you if you come from C-like languages, and things you need to watch out for.
Now, since I effectively learned to program in C and later C#/Java, ___ for node developers isn't what I'm after, especially if it spends a bunch of time talking about static typing or fixed size arrays and such. But if you're going the opposite way as I did, learning the high level and transitioning to the low level, something like that could be very useful indeed.
I know it’s not a popular opinion with some, but all code looks like to me anymore is math with whatever symbols the language in question needs to work
For example:
(singleton)
(tu,ple)
def func1(singleton):
def func2(tu,ple):
^ python function declarations
So after 20 yrs of this, I try to keep in mind the math and just look up the bits to wrap it in.
Also, I avoid custom frameworks and all this industry react/angular, or whatever is cool like the plague, by avoiding front end for a while now
But I do consulting which affords me the luxury. Many may not have the flexibility.
I’ve a set of macros in vim to scaffold boiler plate and go from there
Why would this author feel compelled to write an article about this if they're just learning? That asynchronous Go code which is meant to be analogous to the handful of Node lines looks super verbose. Because the author has claimed a lack of expertise, I have no idea if that is actually the correct way to write something like that out...but it certainly doesn't make Go look good.
> Why would this author feel compelled to write an article about this if they're just learning?
Why wouldn't they? They specifically claim lack of expertise, and that sets the expectations for the reader.
The author is just telling their story about learning Go coming from javascript/nodejs. Whether or not you like the book doesn't mean it shouldn't have been written.
I myself know I learn better when I write things I have learned down. I have written very similar blog posts myself, a couple of which actually ended up on HN.
It’s a really weird experience writing something you figure no one will ever read, and suddenly one day months later having to field mass criticism.
The biggest difference I see: the author immediately reached for a framework instead of checking out the standard library.
In Node, the standard library is effectively non-existent, so Node devs get trained and acclimatised to dependencies.
In Golang, dependencies are minimised. Everyone tries to stick to the standard library as much as possible. Because the standard library is so good, for most projects this is perfectly reasonable.
I'd say the first thing every Node dev should know when learning Go is that they don't need a dependency manager. If you can't do it with the standard library then you're probably doing it wrong (at least until you've got some experience with the library).
Good is _really_ subjective.
While its definitely better than JS/Node it has some warts.
For example, I find the "time" builtin package to be pretty terrible. Specifically how it does formatting[0]. This method makes the format look like a magic string rather than being an obvious template like other languages would use.
I've found some legitimate bugs[1] in simple functions that don't give me a ton of confidence in it either.
Personally I find the standard libraries in the likes of Python and .NET Core much more comprehensive, intuitive, and reliable.
I often see time.Parse as a common complaint - but my code is much more readable when I can see what the date format looks like, rather than trying to interpret the cryptic syntax which differs from language to language.
It's sure not perfect, and it's impossible to please everyone but I think it was worth the experiment.
I wouldn't exactly call Go's standard library _good_. It's got a lot of stuff in it, which is nice, but the API design ranges from excellent (net/http) to "how much crack?!" (time.Format and .Parse) to not-quite-sufficient (various packages).
And of course, standard library APIs age with time. Perl and Python are good examples. Both ship with packages that were really good in their day, but have long since been superceded by community-created tools. But the core has to keep shipping the old thing for backwards compat and the maintainers are reluctant to add yet another package that does the same thing.
Dependencies have their downsides, but being able to assemble the best of what's out there rather than relying on the best of what was available at some point in the past has a lot of advantages too. Languages with good dependency management seem like the best possible option.
Go's refusal to embrace this is a huge pain point. Dep is a decent start, but without a community actually doing things like releases, changelogs, and all the other things that go into a solid ecosystem, it's a half measure at best.
> Go's refusal to embrace this is a huge pain point. Dep is a decent start, but without a community actually doing things like releases, changelogs, and all the other things that go into a solid ecosystem, it's a half measure at best.
Go has indeed embraced it and is working on `dep` the officially sanctioned dependency manager.
>In Golang, dependencies are minimised. Everyone tries to stick to the standard library as much as possible.
i don't understand this. yes net/http is nice but there's no router, there's no orm (yes i know that's not really possible at all because of strong typing), yes database/sql exists but you know most everyone uses at least sqlx and e.g. lib/pq. yes html/template is nice but we're all doing SPAs now anyway. okay there's logging but e.g. no websockets. so in what sense is the stl really complete? what modern web app could you write with just the stl?
You don't need a router (especially for an SPA with client-side routing). If you've got less than 20 or so routes, then a big switch statement is all the routing you need. Learning to write "proper" logic around routes instead of parsing them with regexes was a learning milestone for me.
You don't need an ORM. Mapping database tables to objects directly is a really bad idea. Write SQL, it's easy, simple and cheap. Yes, you'll repeat yourself. Golang generally prefers some repetition to some dependency.
You don't need middleware. Once you get used to handling routes as logic, then the need for middleware kinda vanishes.
You can use the semi-official google websockets package [0]. It's borderline whether this could be considered part of the standard library or not (I use the google uuid package all the time for the same reason). I believe there's an intention to include these packages in the standard library at some point, probably Go v2.
I still remember the first time I had to pick apart a gigantic chunk of java code and found a big switch statement at the center instead of a web of introspectively discovered implicitly wired reactively chained bean factory factory factories or some such nonsense. The relief was almost palpable.
Readability is, I think, a function of your expectations. If you're used to seeing a particular incantation, it's readable. Personally (emphasis on the personally, which is my point), I don't think it gets much more readable that a great big switch statement.
I see Go community pushing for no framework everywhere. I agree Go std library is good enough but some people prefer the framework magic because they want the stuff done faster.
Community should better be saying try std library if you find it verbose try framework(router+ORM)
It's getting to the point where the Gorilla packages could be considered part of the standard library ;)
I agree, but the point is that you can do this with just the "almost official" package. It's not like you have to use the gorilla package because there's no standard library package.
First, I don't think net/http is nice, but you know what's good about Go? It's so modular that you can replace the builtin HTTP server with other one you like (gorilla/http for example) and your code _can_ just continue to work without modification.
And, Go had many third-party Router, ORM, Websocket and Template Engine implementations out there, many of them are also proud to be ... independent, so you're less likely to end up in a Dependency Hell.
Go standard library is not there to force people to use it, rather, it's there to setup a standard so different people can work together more effectively.
So:
> in what sense is the stl really complete? what modern web app could you write with just the stl?
1, It's huge, but not complete;
2, You can actually do it with just Go standard library (No third-party package) if you REALLY wants to. It's not very hygiene though, you will end up wrap many things up for better project structure (And resulting many packages that you might later proudly put on your GitHub page): Use net/http as HTTP server (Request handling and parsing); use net.Dial to connect database and cache (And write their protocol); html/template for outputting rendered HTML landing page; encoding/json for parsing and outputting API request and respond.
There is totally a router, ServeMux, which while basic is enough for 90% of basic tasks if you structure your requests REST-y.
As for ORM, you should basically never use an ORM, ever. They’re a crutch. Learn SQL, write some basic mappers and your SQL will be so much quicker and more optimized than an ORM can generate. An ORM is literally throwing money out the window.
I've seen teams of Go developers shoot themselves in the foot so many times with their hand-crafted SQL. Yes, they should know SQL and be better. And if they think about it, and focus on it, they are.
But it's the mistakes they don't anticipate making that end up causing impacts on their users. Then they create a fix, but the damage is done.
I think the goal behind a good ORM is not to replace making SQL queries entirely. It's to stop stupid mistakes that result from an uneven distribution of expertise. And if they find some area where performance is particularly sensitive and the ORM is not optimal, they can drop down to raw SQL again.
If your team members all have expertise and your test coverage and code review processes are very thorough, it's probably not necessary. An ORM is not a magic bullet for every team. In the same vein, the dogmatic advice to "always handcraft your SQL" is also not a magic bullet.
yeah, but... same for any code. A team of coders who don't know javascript will create buggy, insecure Node apps. There's nothing about SQL as a coding language that creates this.
It's more that modern coders are used to not having to learn SQL and trusting the ORM to do the thing for them. So when they encounter actual SQL (usually because they need to break the object <-> table mapping) it's all scary and weird.
Back in the day, of course, we had DBA's (DataBase Administrators) to make sure that application devs who didn't know enough SQL to not make a mess of things, didn't actually make a mess of things. And yes, we hated the DBA's because they were always telling us our SQL sucked. Great training though.
So, yeah, your point is valid, but there's a better solution to that problem: hire a DBA
Just to mention a third way - I've been happy with a QueryBuilder on recent projects.
The DB access parts of the code look similar to the rest of the codebase, rather than a chunk of text embedded that looks like ransom note (kidding - I know caps aren't mandatory). Enough fine control to closely influence the generated query. No real performance penalty. There's also a good mocking library available for tests.
> An ORM is literally throwing money out the window.
What? Definitely the opposite. First of all, ORMs are just tools, as the name implies they are object-relational-mappers. That's it, you writing SQL to translate to objects is just you writing an ORM, although a very tiny one.
Modern ORM frameworks are incredibly more productive with better security and reliability than hand-crafted SQL and mapping code. Unless you're working at serious scale, doing custom reporting, or other complex scenarios, they handle 99% of CRUD database operations perfectly well. Wasting time reimplementing an existing tool is quite literally throwing money out the window.
And yet this is reality: again 99% of applications manipulate objects in code, persist the data in relational databases, and map rows to objects just fine. Some mapping is necessary anyway, and from my experience modern ORM frameworks actually handle complex objects and relations much better than fragile hand-written code.
As mentioned, if you're in the 1% scenario where this approach doesn't work then you already know you should be using something else. Not knowing when to use what is a far bigger issue than any problem an ORM can cause.
I think it's more 99% of databases are warped horribly to pretend that objects map to tables.
If you throw away the concept that anything in your database has to map to anything in your code base, then you design better databases. Different databases, more to the point.
Oh ok, so your code just doesn't deal with data in the database then? I dont understand what point you're trying to make here.
You can lay out your tables however you want, and you can then map them to objects using an ORM. That's what mapping means, to translate from domain to another. There's no limit on how things are actually designed and ORMs usually do a much better job of handling all that bulk code for you. Nothing is stop you from writing SQL yourself if you really need something complex but again, you should know when and where that is.
Mapping objects to tables and back is a solved problem.
Let me tell you one thing that isn't solved yet: Serialization of arbitrary objects to json and back.
How do you deal with two refererences pointing to the same object? Duplicate the data?
What about circular references? Give each object an id and save a symbolic reference?
What about polymorphism? Should a json array be turned into an array or an list or a json map turned into an object or a hashmap?
You need a type discriminator attribute.
ORMs have already solved those problems well.
The actual problem is that databases are distributed systems and you still have to write queries with the still 10 times better querybuilder of your ORM. Just try writing raw JDBC queries. It's so painful I'd still use the ORM even if my project only uses native SQL queries via the ORM api.
You will probably now ask what's the point of ORMs if you still have to write queries?
Well, it's in the damn name. Object relational mapper. It maps stuff. It's not advertised as WYQFY. "Writes your queries for you"
> yes net/http is nice but there's no router, there's no orm... yes database/sql exists but you know most everyone uses... yes html/template is nice but we're all...
> what modern web app could you write with just the stl?
Lots. You just have to change your frame of mind.
> i know that's not really possible at all because of strong typing
Once you realise the above, you also realise that most of the time you don't need all that fancy stuff and you just write super boring code that works.
> In Golang, dependencies are minimised. Everyone tries to stick to the standard library as much as possible. Because the standard library is so good, for most projects this is perfectly reasonable.
Meh. The Python stdlib has been considered "good" for a long time[0], but the last few years people commonly reach out for external dependencies.
It's not because the stdlib has gotten less good (the opposite), it's because the experience of publishing and using external dependencies has significantly improved.
> I'd say the first thing every Node dev should know when learning Go is that they don't need a dependency manager.
They do, they just don't have one. Which is why people tend not to bring in external dependencies: bringing in external dependencies in Go is a traumatic experience, much as it used to be in Python a few years back.
[0] in fact this exact same argument was relatively common in the mid-to-late aughts, Java developers dipping their toes into Python would complain about the state of dependency management and get told that the stdlib is so good you don't need dependency management, the stdlib is almost all you need and there's no need for advanced dependency management for just one or two dependencies…
virtualenv solved conflicting dependencies but pip is what made installing & managing them convenient. I see many people who use pip without virtualenvs.
Yeah easy_install, which theoretically worked (kinda), but alongside pip there was also the overall pypa effort (both marketing and technical) to make the whole thing work e.g. update or even fork the more abstruse projects such that they could actually be installed via pip. IIRC that was the primary reason for Pillow forking PIL.
So I am trying to move away from NodeJs for my next project and I can't decide between Elixir and Go. Can't decide what to choose, any idea if there is any advantage for a noob to learn one or the other?
I’d say it depends on what you want to build (disclaimer: I have written a lot of Go but have only read Elixir source). If full stack monolith, use Elixir because of Phoenix; if microservice arch, use Go with gRPC protobufs for messaging.
IMO, both languages seem to result in very readable source code; and many examples of how to do either exist on GitHub.
Scaling parts of the application independently from each other. If traffic spikes in one part of the application (e.x.: your image categorization web app was posted in a cat forum) more nodes can be added to that one resource to handle the load. Another reason could be worker processes that ran intermittently at midnight every day (e.x.: to email users top pics they missed that day).
Isn't that the whole point of the Erlang/Elixir/OTP actor model and BEAM VM? It seems like many systems with microservice architecture are reinventing that wheel only worse - except in the cases where the system needs to use legacy or polyglot services.
The difference is in the network boundaries. I write most of my code as microservices, but it would be incredibly easy to wrap it all up into a single binary.
It's not uncommon for go code to have one binary for separate microservice functions (see OKLog). This way you can change between a microservice, or a monolith (ish) with a CLI flag.
Do both and and then make an educated decision on which languages fits best for the project goals. They are different tools. But to be honest, I'm an Elixir fan :-)
I built a web app in Go recently, and while it was enjoyable, progress was pretty slow. I eventually decided to change gears and rebuild it in Elixir, and so far I have no regrets. Phoenix is pretty fast, awesome, and powerful. There are a few concepts you have to learn, but overall it's been a much simpler experience and way faster to prototype with.
I don't think getting started is hard, but diving into the heavy concepts could be overwhelming. Macros can be weird, and I still have to think through a lot whenever I make a foreign table relation in Ecto, since you have to create the migration (which is a way to build your database with code) AND the changeset (which is basically an elixir object that maps to the table).
Anyways, Elixir is functional, which isn't that difficult. Javascript is partially functional, but if you're used to Java or C++ you'll want to approach it with an open mind. If you've ever used F#, or C# with LINQ before, then you'll be familiar waters.
I bought the Programming Phoenix book, and it does a pretty good job, but with Phoenix 1.3 it's already out-of-date. However, it's still good reference material for the underlying concepts.
This list of open-source phoenix apps has saved my ass a couple times as well. I probably look at changelog.com's source the most since it's by far the most active project here: https://github.com/droptheplot/awesome-phoenix
I know it's not the most helpful information, but truth be told there's no secret to learn it, you just gotta do it and fuck it up a few times to get it right.
When I decide about a tool/language (I have learned now dozens) I just think in the HARDEST task that I could possible anticipate. Also, I do some basic stuff. In my case, I try to see how well is to interface with RDBMS.
I try to do it with them and then decide.
So, in short, build a mental "benchmark" that is representative to help to decide if X is right for you
I don’t see why you move away from Node unless it was for a JAVA spring boot or .net core, especially now that node has actually begun to enter real world usage and enterprise on a large scale.
Then again I would have said something similar about picking up Node in the earlier days, so who knows.
I doubt Go and Ekixir will ever gain the same reach Node has though. Node has the advantage of JavaScript being an unavoidable part of your web stack, so it’ll always have value. With more and more IoT picking up Node as well, it has a bright future.
Given the two choices, I’d go with Elixir. Golang is hyped in America, but it has really terrible production times and isn’t really good at anything except a few use cases.
This won’t be a popular opinion, but my context is Danish enterprise, and I’ve never seen anyone hire a Go or Elixir programmer, and I honestly doubt I ever will because the majority of our backend workforce is either JAVA or .Net.
Learning new tech is great of course, but I’d rather hire someone who was really great at one particularly stack than someone who was mediocre at multiple. Anyone can make a simple web-app in Go, Node, Elixir, Django, Asp or Java, but what I would need my hires to do was things like OIOSAML authentication with ADFS, and if you can’t do that because you learned Go instead of playing around with passport.js, you’d quite honestly not get hired.
I'm looking for a web job in Paris at the moment and there is definitely many Go offering, maybe not be as much as Java or C# (I don't look for those) but still.
Also I went to the last Elixir meetup and there is some companies hiring, but it's obviously very new.
Why not both? Take the most popular web frameworks and see how quickly you ramp up in say a week or two week sprint.
I'm more of a fan of the Ruby syntax and the Phoenix framework is definitely a breath of fresh air. My next web project wants to be with Elixir but for a generic cross platform cli program, I'm eager to learn Go.
Is there really anything else in Go than "pretty good standard library". Looking at this and many other Go discussion it seems there isn't.
I've been using Go for a while now and while standard library is ok and definitely better than the one in Node.js and I really like strong typing, I still have to say Go is probably one of the worst programming languages I have ever seen in my life.
Error handling is from the stone age, no support for generics, no support for functional programming, no real enum but instead "a hack" you have build by yourself, dependency management without versions etc.
Also the hyped features such as channels are nice, but nothing a simple Rx-library couldn't do.
Due to the language limitations it's also nearly impossible to write elegant code with Go. If you take a look at any codebase, build by experienced senior developer or junior dev straight out of college/high school the code is almost always the same:
> Is there really anything else in Go than "pretty good standard library".
An easy to understand language spec, a compiler that can spit executables that don't depend on glibc, no dependencies on Python 2, and most (if not all) packages under /x/ are BSD licensed.
> Error handling is from the stone age
I actually prefer this approach to explicit error handling, as opposed to the trendy "uncontrolled non-local gotos" approach (a.k.a. "exceptions". I'm borrowing that term from someone else).
The only sane-ish approach to exceptions I'm aware of is that of Java, where you explicitly have to tell which exceptions can happen, and force you to either handle them right there, or modify your function signature accordingly.
Still, with a big `try/catch`, if two calls throw the same exception, both exceptions would go to the exact same `catch` block.
Yeah, thanks, but I appreciate how Go makes ignoring errors very eye-catching. Makes code review easier.
> no support for generics
Devs are actually very open to generics. The thing is, nobody has, as of yet, proposed any implementation that would play nice with the rest of the language.
> no support for functional programming
I don't see the problem. It's not like every new programming language should support every possible feature known to humanity. They would end up like C++, where you don't know if the next version will add the Unreal Engine to the stdlib.
If anything what we need is more minimalist programming languages, not the next bloat of the century.
> no real enum but instead "a hack" you have build by yourself
I can see the point here.
> dependency management without versions
This is actually one of the things I like the most about Go. "Fix your thing to work with the latest version, or bundle your working version", sounds very reasonable to me.
No concept of versions, no centralized source for anything. Just repositories and an ad-hoc way to setup your "registry" just by including an HTML tag in a web server you own.
The only assumptions made about "packaging" is that (1) they're somewhere on internet, and (2) you have the command necessary to fetch them.
If anything, what I don't like about `go get` is that adding a new "handler" requires recompiling the `go` executable.
> Also the hyped features such as channels are nice, but nothing a simple Rx-library couldn't do.
Sure. Go brings nothing new to the table.
> Due to the language limitations it's also nearly impossible to write elegant code with Go.
Most Go code looks elegant to me. Same formatting everywhere (except when someone does not use `gofmt`).
It also means that whenever I see `a + 1`, and the code compiles fine, I know it's a numeric addition, and not an HTTP request, for example.
Go is like a language with some linting in the spec. Compiler error for unused variables? Yes thanks!
Makes reviewing code easier.
> If you take a look at any codebase, build by experienced senior developer or junior dev straight out of college/high school the code is almost always the same
Looks like a plus to me.
> Tons of "if err != nil"
I don't know, I always considered a good practice to handle errors as soon and as explicitly as possible.
> and for loops.
WHAT!? No more `for (;;) {}` vs `while (1) {}` discussions!!!11!1!!ONEONE.
Making people think twice before introducing the Go equivalent of `Array.prototype.forEach` vs `_.each` vs `$.each`, looks like a plus to me as well.
Working as close as possible to the primitives unless strictly necessary.
> If you take a look at any codebase, build by experienced senior developer or junior dev straight out of college/high school the code is almost always the same
I think that's kind of the point though. Go gives you one way to do things, and makes it really easy to read no matter what your level. It makes things very boring, which imo is a good thing in lots of cases. Its also terrible for some use cases because it is quite verbose (as you mentioned, err != nil can get tiresome if errors don't matter much), so you gotta find a good balance.
81 comments
[ 2.3 ms ] story [ 155 ms ] threadProfessional Javascript for Web Developers[1] is a favorite of mine, because it doesn't waste time teaching you to program and teaching you the language. Instead it points out things that will surprise you if you come from C-like languages, and things you need to watch out for.
Now, since I effectively learned to program in C and later C#/Java, ___ for node developers isn't what I'm after, especially if it spends a bunch of time talking about static typing or fixed size arrays and such. But if you're going the opposite way as I did, learning the high level and transitioning to the low level, something like that could be very useful indeed.
[1]: https://www.amazon.com/Professional-JavaScript-Developers-Ni...
For example:
(singleton)
(tu,ple)
def func1(singleton):
def func2(tu,ple):
^ python function declarations
So after 20 yrs of this, I try to keep in mind the math and just look up the bits to wrap it in.
Also, I avoid custom frameworks and all this industry react/angular, or whatever is cool like the plague, by avoiding front end for a while now
But I do consulting which affords me the luxury. Many may not have the flexibility.
I’ve a set of macros in vim to scaffold boiler plate and go from there
Boom, programming in any language
https://news.ycombinator.com/newsguidelines.html
https://news.ycombinator.com/newswelcome.html
Why wouldn't they? They specifically claim lack of expertise, and that sets the expectations for the reader.
The author is just telling their story about learning Go coming from javascript/nodejs. Whether or not you like the book doesn't mean it shouldn't have been written.
It’s a really weird experience writing something you figure no one will ever read, and suddenly one day months later having to field mass criticism.
In Node, the standard library is effectively non-existent, so Node devs get trained and acclimatised to dependencies.
In Golang, dependencies are minimised. Everyone tries to stick to the standard library as much as possible. Because the standard library is so good, for most projects this is perfectly reasonable.
I'd say the first thing every Node dev should know when learning Go is that they don't need a dependency manager. If you can't do it with the standard library then you're probably doing it wrong (at least until you've got some experience with the library).
For not needing a dependency manager, Go sure has developed an amazing number of them!
https://github.com/golang/go/wiki/PackageManagementTools
https://github.com/avelino/awesome-go/blob/master/README.md#...
In fact, Go probably has the most package managers of any language I've ever seen.
I've found some legitimate bugs[1] in simple functions that don't give me a ton of confidence in it either.
Personally I find the standard libraries in the likes of Python and .NET Core much more comprehensive, intuitive, and reliable.
[0]: https://golang.org/pkg/time/#Time.Format [1]: https://github.com/golang/go/issues/15852
It's sure not perfect, and it's impossible to please everyone but I think it was worth the experiment.
And of course, standard library APIs age with time. Perl and Python are good examples. Both ship with packages that were really good in their day, but have long since been superceded by community-created tools. But the core has to keep shipping the old thing for backwards compat and the maintainers are reluctant to add yet another package that does the same thing.
Dependencies have their downsides, but being able to assemble the best of what's out there rather than relying on the best of what was available at some point in the past has a lot of advantages too. Languages with good dependency management seem like the best possible option.
Go's refusal to embrace this is a huge pain point. Dep is a decent start, but without a community actually doing things like releases, changelogs, and all the other things that go into a solid ecosystem, it's a half measure at best.
Go has indeed embraced it and is working on `dep` the officially sanctioned dependency manager.
It's under the official golang github repository.
https://github.com/golang/dep/graphs/commit-activity
Agreed that it's a decent start, however I disagree with the lack of releases. If you look at the git history there is a lot of activity in it.
i don't understand this. yes net/http is nice but there's no router, there's no orm (yes i know that's not really possible at all because of strong typing), yes database/sql exists but you know most everyone uses at least sqlx and e.g. lib/pq. yes html/template is nice but we're all doing SPAs now anyway. okay there's logging but e.g. no websockets. so in what sense is the stl really complete? what modern web app could you write with just the stl?
You don't need an ORM. Mapping database tables to objects directly is a really bad idea. Write SQL, it's easy, simple and cheap. Yes, you'll repeat yourself. Golang generally prefers some repetition to some dependency.
You don't need middleware. Once you get used to handling routes as logic, then the need for middleware kinda vanishes.
You can use the semi-official google websockets package [0]. It's borderline whether this could be considered part of the standard library or not (I use the google uuid package all the time for the same reason). I believe there's an intention to include these packages in the standard library at some point, probably Go v2.
Try it out, it's liberating.
0: https://godoc.org/golang.org/x/net/websocket
You don't need middleware, but it is much more readable with r.Use(jwtVerify) then writing a deeply nested half router with logic.
If you're running a single endpoint, then the router is adding zero value.
Community should better be saying try std library if you find it verbose try framework(router+ORM)
Those people should try being maintenance programmers sometime /curmudgeonly-grumble
I agree, but the point is that you can do this with just the "almost official" package. It's not like you have to use the gorilla package because there's no standard library package.
And, Go had many third-party Router, ORM, Websocket and Template Engine implementations out there, many of them are also proud to be ... independent, so you're less likely to end up in a Dependency Hell.
Go standard library is not there to force people to use it, rather, it's there to setup a standard so different people can work together more effectively.
So:
> in what sense is the stl really complete? what modern web app could you write with just the stl?
1, It's huge, but not complete;
2, You can actually do it with just Go standard library (No third-party package) if you REALLY wants to. It's not very hygiene though, you will end up wrap many things up for better project structure (And resulting many packages that you might later proudly put on your GitHub page): Use net/http as HTTP server (Request handling and parsing); use net.Dial to connect database and cache (And write their protocol); html/template for outputting rendered HTML landing page; encoding/json for parsing and outputting API request and respond.
As for ORM, you should basically never use an ORM, ever. They’re a crutch. Learn SQL, write some basic mappers and your SQL will be so much quicker and more optimized than an ORM can generate. An ORM is literally throwing money out the window.
https://golang.org/pkg/net/http/#ServeMux.Handle
But it's the mistakes they don't anticipate making that end up causing impacts on their users. Then they create a fix, but the damage is done.
I think the goal behind a good ORM is not to replace making SQL queries entirely. It's to stop stupid mistakes that result from an uneven distribution of expertise. And if they find some area where performance is particularly sensitive and the ORM is not optimal, they can drop down to raw SQL again.
If your team members all have expertise and your test coverage and code review processes are very thorough, it's probably not necessary. An ORM is not a magic bullet for every team. In the same vein, the dogmatic advice to "always handcraft your SQL" is also not a magic bullet.
It's more that modern coders are used to not having to learn SQL and trusting the ORM to do the thing for them. So when they encounter actual SQL (usually because they need to break the object <-> table mapping) it's all scary and weird.
Back in the day, of course, we had DBA's (DataBase Administrators) to make sure that application devs who didn't know enough SQL to not make a mess of things, didn't actually make a mess of things. And yes, we hated the DBA's because they were always telling us our SQL sucked. Great training though.
So, yeah, your point is valid, but there's a better solution to that problem: hire a DBA
The DB access parts of the code look similar to the rest of the codebase, rather than a chunk of text embedded that looks like ransom note (kidding - I know caps aren't mandatory). Enough fine control to closely influence the generated query. No real performance penalty. There's also a good mocking library available for tests.
What? Definitely the opposite. First of all, ORMs are just tools, as the name implies they are object-relational-mappers. That's it, you writing SQL to translate to objects is just you writing an ORM, although a very tiny one.
Modern ORM frameworks are incredibly more productive with better security and reliability than hand-crafted SQL and mapping code. Unless you're working at serious scale, doing custom reporting, or other complex scenarios, they handle 99% of CRUD database operations perfectly well. Wasting time reimplementing an existing tool is quite literally throwing money out the window.
No. Absolutely not. This is the fundamental mess that ORMS create.
Objects DO NOT map cleanly to tables.
Eventually your code discovers this, and suddenly it's a world of pain because the ORM can't handle it.
As mentioned, if you're in the 1% scenario where this approach doesn't work then you already know you should be using something else. Not knowing when to use what is a far bigger issue than any problem an ORM can cause.
If you throw away the concept that anything in your database has to map to anything in your code base, then you design better databases. Different databases, more to the point.
You can lay out your tables however you want, and you can then map them to objects using an ORM. That's what mapping means, to translate from domain to another. There's no limit on how things are actually designed and ORMs usually do a much better job of handling all that bulk code for you. Nothing is stop you from writing SQL yourself if you really need something complex but again, you should know when and where that is.
Let me tell you one thing that isn't solved yet: Serialization of arbitrary objects to json and back.
How do you deal with two refererences pointing to the same object? Duplicate the data?
What about circular references? Give each object an id and save a symbolic reference?
What about polymorphism? Should a json array be turned into an array or an list or a json map turned into an object or a hashmap?
You need a type discriminator attribute.
ORMs have already solved those problems well.
The actual problem is that databases are distributed systems and you still have to write queries with the still 10 times better querybuilder of your ORM. Just try writing raw JDBC queries. It's so painful I'd still use the ORM even if my project only uses native SQL queries via the ORM api.
You will probably now ask what's the point of ORMs if you still have to write queries? Well, it's in the damn name. Object relational mapper. It maps stuff. It's not advertised as WYQFY. "Writes your queries for you"
Three fallacies of dependencies: https://www.youtube.com/watch?v=yi5A3cK1LNA
> what modern web app could you write with just the stl?
Lots. You just have to change your frame of mind.
> i know that's not really possible at all because of strong typing
Once you realise the above, you also realise that most of the time you don't need all that fancy stuff and you just write super boring code that works.
This. This is the essence of Go to my mind :)
Have you ever actually taken a look at it? https://nodejs.org/api/index.html
> In Golang, dependencies are minimised. Everyone tries to stick to the standard library as much as possible. Because the standard library is so good, for most projects this is perfectly reasonable.
Meh. The Python stdlib has been considered "good" for a long time[0], but the last few years people commonly reach out for external dependencies.
It's not because the stdlib has gotten less good (the opposite), it's because the experience of publishing and using external dependencies has significantly improved.
> I'd say the first thing every Node dev should know when learning Go is that they don't need a dependency manager.
They do, they just don't have one. Which is why people tend not to bring in external dependencies: bringing in external dependencies in Go is a traumatic experience, much as it used to be in Python a few years back.
[0] in fact this exact same argument was relatively common in the mid-to-late aughts, Java developers dipping their toes into Python would complain about the state of dependency management and get told that the stdlib is so good you don't need dependency management, the stdlib is almost all you need and there's no need for advanced dependency management for just one or two dependencies…
few years back being pre-2011, with pep 405[0] and virtualenv[1] solving most of the nostalgic py dep hell problems.
venv's been a option since 2007, only getting pep'ed later?
[0] https://www.python.org/dev/peps/pep-0405/
[1] https://virtualenv.pypa.io/en/stable/changes/#id54
Initial pip release was also 2011. Now I wonder what I used pre-pip?!
edit: easy_install, doh!
Where do I have to sign?
IMO, both languages seem to result in very readable source code; and many examples of how to do either exist on GitHub.
It's not uncommon for go code to have one binary for separate microservice functions (see OKLog). This way you can change between a microservice, or a monolith (ish) with a CLI flag.
I would say go with Elixir or even better, Erlang. It will open your mind to new ideas.
I don't think getting started is hard, but diving into the heavy concepts could be overwhelming. Macros can be weird, and I still have to think through a lot whenever I make a foreign table relation in Ecto, since you have to create the migration (which is a way to build your database with code) AND the changeset (which is basically an elixir object that maps to the table).
Anyways, Elixir is functional, which isn't that difficult. Javascript is partially functional, but if you're used to Java or C++ you'll want to approach it with an open mind. If you've ever used F#, or C# with LINQ before, then you'll be familiar waters.
I bought the Programming Phoenix book, and it does a pretty good job, but with Phoenix 1.3 it's already out-of-date. However, it's still good reference material for the underlying concepts.
This list of open-source phoenix apps has saved my ass a couple times as well. I probably look at changelog.com's source the most since it's by far the most active project here: https://github.com/droptheplot/awesome-phoenix
I know it's not the most helpful information, but truth be told there's no secret to learn it, you just gotta do it and fuck it up a few times to get it right.
Having said that, I would suggest the GP try both. I'm keen to try my hand at Elixir soon.
I try to do it with them and then decide.
So, in short, build a mental "benchmark" that is representative to help to decide if X is right for you
Then again I would have said something similar about picking up Node in the earlier days, so who knows.
I doubt Go and Ekixir will ever gain the same reach Node has though. Node has the advantage of JavaScript being an unavoidable part of your web stack, so it’ll always have value. With more and more IoT picking up Node as well, it has a bright future.
Given the two choices, I’d go with Elixir. Golang is hyped in America, but it has really terrible production times and isn’t really good at anything except a few use cases.
This won’t be a popular opinion, but my context is Danish enterprise, and I’ve never seen anyone hire a Go or Elixir programmer, and I honestly doubt I ever will because the majority of our backend workforce is either JAVA or .Net.
Learning new tech is great of course, but I’d rather hire someone who was really great at one particularly stack than someone who was mediocre at multiple. Anyone can make a simple web-app in Go, Node, Elixir, Django, Asp or Java, but what I would need my hires to do was things like OIOSAML authentication with ADFS, and if you can’t do that because you learned Go instead of playing around with passport.js, you’d quite honestly not get hired.
That's why i'm starting to avoid as much as possible all new/updated online services for serious stuff.
Also I went to the last Elixir meetup and there is some companies hiring, but it's obviously very new.
I'm more of a fan of the Ruby syntax and the Phoenix framework is definitely a breath of fresh air. My next web project wants to be with Elixir but for a generic cross platform cli program, I'm eager to learn Go.
I wrote comment to him:
It's only natural that you're trying to find solutions for problems you encountered in past.
But exploring new technology this way leads to absolutely natural mistakes. You're are worring about wrong things.
Dependency management This problem is not (and never was) in such terrible scale as in javascript.
You can forget about this problem while you learn go. I suppose that dep will be released offically when you will really need this.
Asynchronicity I did the same mistake as you: I thought that channels and messages are similar to Actor pattern in Erlang, Akka.
Don't try to think about promises, futures and other abstraction when you programming in go.
In fact, you need learn synchronicity now, golang already asynchronous in its nature.
I've been using Go for a while now and while standard library is ok and definitely better than the one in Node.js and I really like strong typing, I still have to say Go is probably one of the worst programming languages I have ever seen in my life.
Error handling is from the stone age, no support for generics, no support for functional programming, no real enum but instead "a hack" you have build by yourself, dependency management without versions etc.
Also the hyped features such as channels are nice, but nothing a simple Rx-library couldn't do.
Due to the language limitations it's also nearly impossible to write elegant code with Go. If you take a look at any codebase, build by experienced senior developer or junior dev straight out of college/high school the code is almost always the same:
Tons of "if err != nil" and for loops.
Not boring. Just "full of boilerplate" which also means that it will be a nightmare to maintain at a certain point of the lifecycle.
An easy to understand language spec, a compiler that can spit executables that don't depend on glibc, no dependencies on Python 2, and most (if not all) packages under /x/ are BSD licensed.
> Error handling is from the stone age
I actually prefer this approach to explicit error handling, as opposed to the trendy "uncontrolled non-local gotos" approach (a.k.a. "exceptions". I'm borrowing that term from someone else).
The only sane-ish approach to exceptions I'm aware of is that of Java, where you explicitly have to tell which exceptions can happen, and force you to either handle them right there, or modify your function signature accordingly.
Still, with a big `try/catch`, if two calls throw the same exception, both exceptions would go to the exact same `catch` block.
Yeah, thanks, but I appreciate how Go makes ignoring errors very eye-catching. Makes code review easier.
> no support for generics
Devs are actually very open to generics. The thing is, nobody has, as of yet, proposed any implementation that would play nice with the rest of the language.
> no support for functional programming
I don't see the problem. It's not like every new programming language should support every possible feature known to humanity. They would end up like C++, where you don't know if the next version will add the Unreal Engine to the stdlib.
If anything what we need is more minimalist programming languages, not the next bloat of the century.
> no real enum but instead "a hack" you have build by yourself
I can see the point here.
> dependency management without versions
This is actually one of the things I like the most about Go. "Fix your thing to work with the latest version, or bundle your working version", sounds very reasonable to me.
No concept of versions, no centralized source for anything. Just repositories and an ad-hoc way to setup your "registry" just by including an HTML tag in a web server you own.
The only assumptions made about "packaging" is that (1) they're somewhere on internet, and (2) you have the command necessary to fetch them.
If anything, what I don't like about `go get` is that adding a new "handler" requires recompiling the `go` executable.
> Also the hyped features such as channels are nice, but nothing a simple Rx-library couldn't do.
Sure. Go brings nothing new to the table.
> Due to the language limitations it's also nearly impossible to write elegant code with Go.
Most Go code looks elegant to me. Same formatting everywhere (except when someone does not use `gofmt`).
It also means that whenever I see `a + 1`, and the code compiles fine, I know it's a numeric addition, and not an HTTP request, for example.
Go is like a language with some linting in the spec. Compiler error for unused variables? Yes thanks!
Makes reviewing code easier.
> If you take a look at any codebase, build by experienced senior developer or junior dev straight out of college/high school the code is almost always the same
Looks like a plus to me.
> Tons of "if err != nil"
I don't know, I always considered a good practice to handle errors as soon and as explicitly as possible.
> and for loops.
WHAT!? No more `for (;;) {}` vs `while (1) {}` discussions!!!11!1!!ONEONE.
Making people think twice before introducing the Go equivalent of `Array.prototype.forEach` vs `_.each` vs `$.each`, looks like a plus to me as well.
Working as close as possible to the primitives unless strictly necessary.
I think that's kind of the point though. Go gives you one way to do things, and makes it really easy to read no matter what your level. It makes things very boring, which imo is a good thing in lots of cases. Its also terrible for some use cases because it is quite verbose (as you mentioned, err != nil can get tiresome if errors don't matter much), so you gotta find a good balance.