It's the new Java, but fewer batteries included, and very easy to learn. I spent a day going over https://gobyexample.com/ and became productive the next day. I tried to do the same with Rust, but I failed. Nobody was able to succinctly explain all the things you have to learn to become productive with Rust, let alone understand anyone else's code, since there are too many different ways of doing the same shit.
I fear generics will make Go go in a worse direction, but I'm not losing sleep over it.
I would even go as far as to say Go is the fastest way to land a $100K/yr job with zero knowledge about programming and still be able to live with yourself (unlike with the JavaScript/npm oligopoly).
Solid Go'ers eschew huge dependencies and prefer classic Unix KISS philosophies. It's a breath of fresh air. And like the performance figures show, your apps magically get slightly faster over the years!
Don't mean to advocate, I've had the opposite experience. I love listening to the guys over at the Go Time podcast, but for simple things I reach for Node (that I desperately want to escape!), and for a better language I reach for Rust, it just feels right, although I completely agree about library code being complex to understand and using a lot of magic to squeeze out every last drop of performance.
As a corollary, I still haven't been able to understand Go modules and the way code is supposed to be laid out! In fact, a Go 1.16 broke one of my npm packages as it deprecated `go get` with no real alternative for my use case, without manually creating a go.mod file for the cloned repository (that I don't own) in question. I guess this creates a natural... distate for said language.
I think if I would have started with Go, I would have loved it from day 1, but now it provides too much friction to get stuff done. Yeah, it's fast (but most new languages are), it fools C programmers into thinking it's like C due to its syntax, but people coming from the functional world which they believe to be the holy grail will run away in fear with the number of mutations (no Array.map or iterators) and pointers flying around. I still haven't managed to get SQLite working with Go on Windows (stop! a lot of developers do use Windows!), the Rust crate just worked.
The only language that I've actually had fun trying out recently is Elixir, which completely surprised me. The AoC challenges were fun to write in it, and honestly still quite fast!
That's fair enough; it's a language you're more confident with. I've spent two years doing Go regularly now, and at the moment I can whip up valid Go code without tooling or running it in between, but it took me a good amount of time and practice.
> As a corollary, I still haven't been able to understand Go modules and the way code is supposed to be laid out!
I also believe these are the biggest challenges in the Go ecosystem at the moment, and it's probably the most frequently asked question in the various communities. Code / codebase layout is still a very opinionated thing, and while there's a handful of good ideas, there's no standard. (on that note, ignore the "golang-standards" github account, those are NOT standards).
> Code / codebase layout is still a very opinionated thing
And will remain so, because there simply is no silver bullet. Does it sometimes make sense to have a "cmd" directory? Absolutely. Does it sometimes make sense to have every subcomponent live its own package? Yes.
I used Node (with Typescript) as well for small and simple stuff. Typescript is probably still my favorite language.
Now, I'm using Go for about 2 years and to my shame I haven't really understood Go modules properly. I still need to look up simple stuff in the standard lib regularly. I can relate that Go is quite different than what many from us coming from other languages are used to. To me, Rust syntax felt much simpler to learn.
However, Go is now my standard tool. Rust takes just too much brain power just for memory management. The Go std lib is a huge time and headache saver. Go gets overall so much right that I learned to live with some of it's quirks.
TypeScript is actually pretty amazing, a lot of people strongly dislike it, but I think it gives a reasonable amount of safety for such a dynamic language, I would use it even if only for the autocompletion. It encourages a better (imo) style of programming than traditional JS that did all kinds of dark magic, like modifying the prototype chain.
Sometimes I wonder what a world with strong ESM support, a slim runtime such as just [1], strong typing (like Rescript is trying to do), a unified format/lint toolchain and a solid standard library would like like, look how far Node.js has gotten despite its numerous flaws.
I just tried it now (a year later), same compiler error (using msys2):
# github.com/mattn/go-sqlite3
/usr/lib/gcc/x86_64-pc-msys/10.2.0/../../../../x86_64-pc-msys/bin/ld: cannot find -lmingwex
/usr/lib/gcc/x86_64-pc-msys/10.2.0/../../../../x86_64-pc-msys/bin/ld: cannot find -lmingw32
collect2: error: ld returned 1 exit status
The go-sqlite3 GitHub repo has tons of Windows-related issues, one just opened yesterday in fact. I'm not an experienced C programmer, I'm not well versed in compiler/linker toolchains, I know it's super tricky (especially on Windows) but I don't expect my clients to be experts either. I actually spent a few hours trying to solve this last time, time I could have spent coding.
It's not a problem with Go, per se, but it does create non-trivial requirements toolchain setup on Windows, which ruled out Go for me. The whole toolchain just feels a bit... flakey, setting up GOPATH and such (although, that seems to no longer be the case?). Rust's crates, just as an example, are amazing, I've never had a single problem with them (more than I can say for npm..) I know it's just one example, but sqlite3 is brilliant. This immediately ruled out Go for me for that project.
> It's not a problem with Go, per se, but it does create non-trivial requirements toolchain setup on Windows, which ruled out Go for me. The whole toolchain just feels a bit... flakey, setting up GOPATH and such (although, that seems to no longer be the case?). Rust's crates, just as an example, are amazing, I've never had a single problem with them (more than I can say for npm..) I know it's just one example, but sqlite3 is brilliant. This immediately ruled out Go for me for that project.
GOPATH is gone, thankfully, and with the introduction of modules. As with many things, crappy tutorials littered around the internet make things difficult. The toolchain itself is pretty damn easy to set up, it "just works" unless you want to use cgo (or one of your modules does), and in that case you're just left hanging. It's pretty clear that go despite _running_ cross platform doesn't particularly care about windows, e.g. the path package basically doesn't support windows natively, the cgo mess, etc.
> Rust's crates, just as an example, are amazing,
Rust has it's own set of problems that you're glossing over here. As an example, many popular crates required nightly last time I looked. Rust's compile times are incredibly painful too, and one of the worst offenders is the #1 json library for rust (serde).
The only popular crate that I can think of that still requires nigthly is Rocket[0], the 0.5 release does not but the lack of maintenance means that it has been three years since 0.4 and months since the last update. In that time Warp, Axum, Tide, Actix and many more frameworks that are all on stable has eaten its lunch. As for long compile times, I agree, it has gotten heaps better but is still far from Go (nor will it ever get that good), but for most my projects with incremental debug builds its in the ballpark of ~2 seconds, which is good enough for me and `cargo check` is close to instant. Release builds, yeah, they are slow.
> Rust's compile times are incredibly painful too, and one of the worst offenders is the #1 json library for rust (serde).
Go and Rust sort of took opposite paths in terms of the compiler.
Rust spends the compilation time (for release compiles) to generate the fastest binaries the compiler can emit. The article talks about Go adding things like "A recent improvement was in version 1.17, which passes function arguments and results in registers" that's stuff that compilers like llvm have been doing pretty much at inception (20 years).
Go has optimized for compilation speed with the understanding that "Well, it's probably not CPU time that is REALLY making your software slow".
Go compiles faster and rust compiles faster results.
They are painful... Running the executable at the end with such a tiny footprint and outstanding predictable performance is very gratifying, however. It feels like the language and the compiler love you, they just have to work a little harder to deal with the complexity of macros and generics!
Yeah, if you use msys2 then you need mingw and such installed. But that's only an issue if you want to compile from a Windows host. You can compile from a POSIX host and target Windows just fine.
There are also pure Go implementations of sqlite3, should you wish to compile from a Windows host and do away with the msys2 dependency.
I'm curious what your clients are if they need to compile the code themselves (which suggests they're using your code as a package?) but which they don't need to use Go (which suggests you could just share them a compiled executable and thus they don't need to resolve this problem themselves). In either case, Go native code would fix that (albeit you don't get that for free -- you'd see a drop in query performance).
The GOPATH issue I never saw as flaky personally. It's one environmental variable, it was dead easy to set up and once it was set it worked fine. But my personal opinions aside, it was unpopular so yes, it no longer needs to be set. Ironically though, I personally think that's made things more complicated than less (or rather it's shifted the complexity elsewhere in the toolchain).
Rust crates are good but you'll find compiling against POSIX C code on Windows to be problematic regardless of the language. Rust just hides that problem because its developers are dogmatic enough that any C code is rewritten in Rust anyway. And Rust is performant enough that such rewrites are usually comparable, often even favorable, in speed to their C counterpart. That rarely seems the case with Go.
So it sounds like there isn't much point trying to solve your issue because you've already rewritten it in another language. However I assure you it is solvable in a number of different ways depending on what your underlying requirements were.
Thank you for your explanation and fair comparison. I'm sure that a seasoned C/Go programmer would skirt around those difficulties or be using POSIX in the first place, I prefer languages that do not impose any constraints on your choice of OS, even if I do prefer Linux for development, but it's not good enough to replace my daily driver.
I don't think there will be a Rust implementation of sqlite3 in the near future, it would be a monumental task. Having the C bindings just work with static compilation in Rust was a deal-maker for that particular personal project, even if it's just because some crate maintainer went to the extra effort to make a robust cross-platform build script and nothing to do with the language itself, it shows that they put in some effort and pride, but I also get tired of the hype and the Rewrite in Rust catchphrase.
I'm a university student, as part of my student job I had to develop a backend application. Someone has to be able to pick it up after me, hence simplicity and easy of use. In the end, I chose Node.js after strongly considering Go, Rust and Elixir that have more cohesive tooling (formatter, linter, better module system!), it was the easiest to justify. I couldn't trust myself to not find any issues/complications with Rust or Go and I just can't afford them running into these issues and explaining to them "oh, you need to set up a C compiler toolchain on Windows".
> I'm sure that a seasoned C/Go programmer would skirt around those difficulties or be using POSIX in the first place, I prefer languages that do not impose any constraints on your choice of OS, even if I do prefer Linux for development, but it's not good enough to replace my daily driver.
It's not Go that imposed that restraint. It was the C API used for sqlite3 that did. There's nothing stopping you using C in Go on Windows without requiring msys2.
> I don't think there will be a Rust implementation of sqlite3 in the near future, it would be a monumental task.
You say that but there's already a pure Go version and Rust ecosystem is famed for rewriting C/C++ stuff. So I wouldn't be so sure.
> I'm a university student, as part of my student job I had to develop a backend application. Someone has to be able to pick it up after me, hence simplicity and easy of use. In the end, I chose Node.js after strongly considering Go, Rust and Elixir that have more cohesive tooling (formatter, linter, better module system!), it was the easiest to justify. I couldn't trust myself to not find any issues/complications with Rust or Go and I just can't afford them running into these issues and explaining to them "oh, you need to set up a C compiler toolchain on Windows".
Sounds like you made a really smart choice there. I'm impressed too because mature judgements like these are a skill even a great many senior engineers lack so to have that kind of foresight while you're still at university is impressive.
You certainly have to set one up for Rust. I'm not sure about Go. Unless I need speed I generally reach for python, but even it sometimes needs a C compiler. I'm surprised the Node.js never needs one? Usually these "higher level" languages end up (on large projects) ultimately calling out to c/c++ libraries of some sort that aren't included in the "native libraries". Is that not true for node.js ?
Yes, Rust guides you though setting up tge MSVC toolchain, then everything Just Works™, I'm not sure which toolchain the Rust sqlite3 bindings crate uses, but it also just works.
Actually, a lot of Node.js is written in plain JS, even large parts of the runtime itself, I've never needed a C compiler. This was mostly to make it easier for contributers that don't want to learn C++.
It's extremely rare for libraries to require any system dependencies, such as a C toolchain. Sharp (libvips bindings) will try to download precompiled binaries from a bucket somewhere, this is all done in ad hoc postinstall scripts, for better or for worse... Other libraries use JS as a C compile target with asm.js, opinions aside, it actually works pretty well.
Go is probably most productive language I'd use for CLI tools and quick server stuff. There are libraries for most things you need, often better documented than python counterparts. Single binary and good tooling.
Now, one may hate something about the language but at the end we bite the bullet and get things done.
That said, Go doesn't have a great ecosystem for website backend dev. You can do it, but often less convenient.
Compared to say Rails/Django, there’s very little magic in the Go ecosystem. You end up rewriting a lot of boilerplate. People would often recommend that you start with bare bones net/http, database/sql, etc., not even a minimal framework like Gin/Echo. This is okay for building performant microservices, but it does get annoying when you’re just trying to spin up your twentieth boring CRUD backend quickly.
as someone not familiar with Go, always wondering why Go people like to recommend the net/http package instead of those framework, are most go backend services actually written from scratch? I find it quite hard to understand since in the Java world it's usually SpringBoot everywhere
I would love to see some "plug and play" user account management. Like handling registration (with confirmation emails), updating/deleting data, build in handling of changing password to increase complexity over time (or forcing change when some leak happen), some protection from login attacks, account levels (and simple adding new level over time), feature toggles, build in multitenancy (so I don't need to code it later when page grow and need it, something like [1]), using ULID (or something similar) instead simple incremental number for ID, build in login history, some login security features (like email on each login, block account login if someone try login from predefined/differen country and email user about that with unblock/allow access link) and more high level stuff (like account anonymising instead of deleting for reporting). So all the stuff that is good to have when you need it but you don't have time to work on it when you focus on business logic.
Do you have any examples of other languages offering typesafe SQL integrations? Not sure what to think of it, given how you'd end up having to map SQL datatypes (across multiple database engines) with Go's own (not very powerful) types or a custom type validation layer (which already moves the problem to runtime instead of compile-time).
I did see a post the other day criticizing Go's standard template language and approach. Maybe someday someone will stand up and build an alternative, more advanced template engine - it can just be a library, after all.
Really, really wanted to use it a few days ago.. but not sure if it's a mysql8 issue but seems most of my "very simple" table definitions couldn't be parsed :/
Looking at the github there seems to a lot of "parsing problems" for the schema files :(
I do like Go, but I have to say I rewrote a small (500 line) Go file I'd written into Rust and was constantly thinking "this is better in Rust". And I suspect that Rust performance would have started pretty much where Go 1.18 is now.
But I definitely agree that reading other people's Go code is a lot easier than Rust. Especially async code. I don't understand why so many people use async outside of web servers which AFAIK is the only place you really need it.
not even necessarily in web servers. If one writes a frontend proxy server which needs to work on > 10k concurrent connections it's likely the way to go. But for an application server which sees much less concurrency it might not matter that much.
It really is becoming the path of least resistance. I'm totally not in love with the language itself, though the whole ecosystem -- runtime platform/performance, community, simple multi-arch compilation -- is awesome!
I like how Tour of Go includes Generics tutorials is simple to grasp on first reading, wasn't difficult as those have been arguing on golang-nut mailing list before Generics was landed.
Well, if pay is the only thing you want to optimize for and you don't enjoy spending time learning about concepts like Rust's borrow checking and lifetimes ... Sure go ahead. But then don't worry later, when other people have way more knowledge accumulated than you did with the easy-going / not learning much approach.
You need to consider, that there are languages, which make use of more advanced or generally less known concepts, and that those concepts take more time than a day to really understand and make use of. Great knowledge and skill is not acquired within a day. It takes time. The "learn in one day" idea sounds more like you only syntax translated previously had knowledge into Go. That enables you to make use of a new ecosystem, which may be great, but it does not enable you to do things in a more intelligent way. You merely switched ecosystems.
I agree with you in general that you should be learning interesting things. But I also agree with ammmir about the productivity of Go. I think there (or should be) two worlds of programming in everyones life. There is the business side, where you aim for quick (and quality) output and productivity, and for the business sake, you aim for high development trajectory so that others can work to improve your code.
I believe this is why PHP was/is so successful and also why Go is so successful. The documentation is solid, contains real world examples, and the environment is easy to get started in (php example.php, go run main.go). The syntax is also very straight forward and easy to make sense of.
And then theres the other world. The things you do outside of business to educate yourself so if the time comes you are prepared. Learning more complex things like Rust, and how ASM works, and the inner workings of the Linux kernel. This is great to learn on your own, and nice to have in your back pocket in the business world if it's required. But for the sake of business growth I think tinkering with these more complex to learn things should be mostly left at home.
I guess it really depends on what type of business you want to run (small team with great talent or large team of decent devs), but at the end of the day I want the code I read at work to be so simple that it's almost boring to look at.
TL,DR: If you do complex things at work, you'll likely be the one getting calls at midnight about it crashing.
15 years ago, I was told I need to learn all about design patterns, and for 10 years after that, I heard about a new OOP-design philosophy almost every month.
Then it turns out wrapping everything into design patterns makes the code harder to read and we are right back to procedural programming.
7 years ago, friends told me I need to learn pure functional programming NOW, because it's the future of programming.
Well, long story short, I still don't know what a Monad is, and the code is still procedural.
Ideally the business side would listen to experienced developers, how to best solve a problem. Developers, who have learned about a lot of things and have widened their horizon. Of course those will only exist, if we encourage learning about lots of concepts. Someone has to do the learning, or else we get stuck at the status quo. Lots of concepts are found in many programming languages. This is why it makes sense to learn quite a few languages at least to some degree, and better, to learn languages, which significantly differ from other language families.
People will always think learning something, which they do not have to learn right now, as the "academic detail/exercise", "non-business" or "not needed". Until they get into a situation, where they lack that knowledge/experience. Like you said, good to have it in your pocket, when you need it. It will be "too late" to learn about something, when one already needs it, unless the hypothetical business allows us time to learn about it then, and does not expect us to know already.
It may be the current situation with developers, but I don't buy into the philosophy of being held back by other developers on the team not educating themselves about stuff. That will be the downfall of many businesses. Of course you should not simply jump on every hype train passing by. Tech choices should have an advantage over the not chosen tech. I wish businesses were wise enough to recognize, that allowing someone to learn for a few weeks might safe them many weeks of debugging and fixing errors later, but the reality is, that you will have best chances, if you already know your stuff.
With Go and Rust the difference is, that very much practically Rust enables you to write safer programs, so that you do not get that call at midnight about something crashing. It is not just something you learn about "outside of the business world", but very much part of doing a good job, by using appropriate tools. If the business world does not allow developers to choose good tools for their job, then the business world should not call at midnight.
One goal of learning is to avoid making the mistakes others have made many times before you. While Go makes concurrency easily accessible, the Rust compiler watches over your shoulder and points out many mistakes to you. How will you practically match the level of safety in concurrent scenarios using Go? If you are not a PLT/type systems expert and concurrency expert with lots of time to write some kind of code that gives similar guarantees, I would say it is not practical to try to get close to the level of safety.
Using a safer or a more concept heavy language does not necessarily mean, that the resulting program or its code will be more complex. The opposite can be true, as the system does more for you already. You might have to write a lot of code in Go to get the same guarantees of safety, or you will need to have really long thinks when changing anything, because the type system does not protect you like in Rust and any change could introduce a concurrency bug. You will need to write more tests, if you want something as safe. Those might be concurrency tests, which are notoriously hard to write. All that code will be gone, as the Rust type system and compiler take care of that for you. Of course Rust will not be perfect either and find every single mistake. It is about avoiding as many mistakes as one can with reasonable effort.
Lets get away from the idea, that learning Rust is very hard. It is a programming language with quite a few very common ideas. Many things we usually already know from other languages, which we learned earlier. There are new ideas as well, obviously, but I would expect every developer to be able to cope with that. It's not like it is an impossible task.
It's the new Java, but fewer batteries included, and very easy to learn. I spent a day going over https://gobyexample.com/ and became productive the next day. I tried to do the same with Rust, but I failed. Nobody was able to succinctly explain all the things you have to learn to become productive with Rust, let alone understand anyone else's code, since there are too many different ways of doing the same shit.
I fear generics will make Go go in a worse direction, but I'm not losing sleep over it.
I would even go as far as to say Go is the fastest way to land a $100K/yr job with zero knowledge about programming and still be able to live with yourself (unlike with the JavaScript/npm oligopoly).
Solid Go'ers eschew huge dependencies and prefer classic Unix KISS philosophies. It's a breath of fresh air. And like the performance figures show, your apps magically get slightly faster over the years!
Life is short, use Go.