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).
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.
Does it always make sense? No.
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.
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.
# 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.
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).
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.
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.
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".
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.
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.
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.
[1]: https://blog.checklyhq.com/building-a-multi-tenant-saas-data...
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.
Either it analyzes the given SQL to determine the in/out types of each SQL query, or it calls the database describe feature at compile-time.
Looking at the github there seems to a lot of "parsing problems" for the schema files :(
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.
The actual browser doesn't need async.
When I say "need" I mean that it provides a decent performance increase.
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.
Life is short, learn interesting things.
The interesting thing about software engineering to me, is not the features of the languages, its the programs I get to write in them.
I don't learn programming languages because I want to know the latest concepts in language design, I learn them so I can write interesting software.
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.
The thing is, how many times did "the time come"?
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.
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.