I actually think this is a bit too much magic:
> import _ "embed"
> //go:embed hello.txt
> var s string
> print(s)
But the embed.FS example looks much nicer, I'm glad we can have both.
As a bonus, if you typo the "include_bytes!" macro, as say "includ_bytes", you get a compiler error.
With the go one, if you typo it as "//gp:emebd hello.txt", then you get no compilation error, just an empty string.
If someone compiles your program with an old version of the go compiler, they get no error, just a totally broken program.
Meaningful comments are some of the worst magic you can add to a language IMO.
It's far simpler to reason about compiler-checked preprocessor instructions or macros, both of which are valid alternatives the go team could have added just as easily.
Also, go users have _already_ started parsing comments for magic strings, so it's not like setting an example of using comments is stopping users from doing this crap too.
A macro language which is defined in a clear and consistent way definitely seems less magic than a macro language which has no real definition, other than examples of comments.
Actually now - the import protects from that.
If you want a new compiler feature, add a new statement.
Otherwise these magic comments will grow into their own unaudited meta language with no formal spec, just a few usage examples.
This and struct tags (another stringy metalanguage) are the bits I’m not keen on in Go.
The go 1 guarantee only says that existing go programs will continue to compile correctly on new releases. It doesn't say that new programs will compile correctly on old releases.
Forgive my ignorance, when would you recommend go? As in what problem domains have you seen it excel at?
I have thought about trying it in the past and even tinkered with a project for a bit but didn't quite find it useful enough to be worth the tooling cost (at the time). Would like an excuse to check it out again.
Go is pretty good for almost anything server-side. I wrote a web server in Go that a lot of businesses use in production. It's a very practical "get things done" language and is generally associated with developer satisfaction/happiness. Almost anywhere you use C/C++, I would try to use Go.
It's progbably easier to enumerate what Go is not good at: native GUIs, C interop, some kinds of data science (though I used it as much as Python in college), and some kinds of very low-level programming (though it can be good for embedded systems, if you can stomach large binaries).
Which aspects do you like? Personally I have grown to dislike the pointless abstraction and obfuscation introduced by huge inheritance hierarchies, so Go is a breath if fresh air in that regard in just doing away with it all. I haven't missed classes at all.
If you try to recreate inheritance in Go it will be frustrating and not very useful.
The shape of the code ends up very different and embedding is not used even half as much as inheritance (which is the default position in most other oop languages). That has profound impacts.
inheritance is just like in COM via delegation and struct embedding.
That is how component based programming works.
COM/UWP have proven you don't need to have it available.
They get lots of hate due to their underlying complexity, however they are the main Windows APIs since Vista, as COM took over the Longhorn vision.
IMO, If you compare Go to an OOP language that runs in a VM there are some things that will fall short but the industry has worked around it. It's not cool to have a beefy Smalltalk or Java VM, with the dynamic runtimes that let you auto-export objects as remote endpoints... you have small binaries exporting HTTP or RPC services running in containers and interfacing with service discovery and fabric systems. The "object orientation" is now at an abstraction sitting above the running binary.
I'm not sure why an application running in the JVM in a container is any different. Can you elaborate?
If someone asks me to build something and they tell me it will run in docker/kubernetes, have the standard containerized CI pipelines, and communicate with other services over some standard protocol like HTTP; doing it on the JVM is doable and probably easier than ever but I would just think about all the cool JVM features I wouldn't get to use (hot code deploy, runtime modularity tools, all the neat bytecode hacks, even spring which everyone but me seems to hate).
If I don't get to use those features then I would rather grab a language like Go, since it doesn't front load so many runtime complexities. (and if this was 10-15 years ago maybe I'd say "Go doesn't front load so many complexities AND performance penalties")
If you install the Gtk libraries on the Mac, Go programs written with gotk3 just compile and run there too.
GUI libraries often rely on specific language features so they are hard to wrap in other languages. That's why good GUI libraries don't exist in ANY language other than the ones they were written in.
Absolutely! REST API servers, data processing jobs, messaging servers, etc etc. I use Go now for virtually everything server side. It is fast, reliable, great tooling, promotes unit testing, and now that I have hit that "comfortable with the language" spot, I have never been more productive.
I'd argue node.js is even easier to learn and even better for getting something useful deployed faster.
- Did your TypeScript properly import all of the @types packages required for it to compile properly? They need to be installed alongside the source packages and match the version numbers. They are often maintained separately and may not match the underlying implementation of the code.
- How do you run this in production? Do you check the compiled TypeScript into the git repo? Do you run with ts-node? Do you do different things in production, development, and test?
- Do all of your native dependencies support the node versions you're using? How do you install the correct version of node? If you ignore these issues by using Docker, how are you managing your images and containers?
The list of problems requiring solutions goes on and on. And of course those solutions exist, but this is a summary of why node projects are not "easy to learn". Don't get me wrong, Node can still be the right tool for the job, in particular if you're sharing a lot of code between an app and something that will run in the browser.
I do a lot of golang but whenever I want to do something web browser facing, I cave in for nodejs. Especially in the exploratory phase when building front / back end together.
Everything I've needed has always been a `require()` or `npm add` away.
Btw thanks for that.. I recently moved to a new VPS and migrated from nginx to Caddy.. I love it.
Arguably, that's more because of the way you can pretty much completely rely on io.Reader and io.Writer being used pervasively throughout the ecosystem (3rd party libraries and all) rather than any specific "Go" special sauce, but, it is what it is.
I would like to compute a load factor and refuse new requests. Or do some basic rate limiting. But the coroutine is spawned before I have a say...
Even if you consult something per request, goroutines are fast enough to look at something and then decide not to do the work that, again, by the time that's a problem, the solution is to throttle upstream anyhow.
As the load increase you enter the territory of queueing (add latenxy) up to a point. Then reject/drop requests. If the rejection is slower than the OS/hardware can provide the software crashes.
For Go it appears that the curve is an almost straight vertical line to oblivion.
But of course if you plan to scale and use a dedicated software to pace requests, there is no point into adding this complexity to the Go libraries.
Maybe what I lament here. Is that this tradeof made by Go is not more advertised. Such that when the day comes that the dreaded out of memory killer shows up, you are ready to fight back.
I think when considered in isolation, Go would be perfect for this. However, I haven’t used it because my existing code in this area is in C++ and I’m not sure how well the two languages interoperate.
I have wrapped a large C++ library for Go it was a pretty straight forward process. I created a file with C callable functions that get passed pointers to the C++ objects and invoke the corresponding methods on that object. On the Go side pointer gets wrapped in a struct type for each C++ class and in the methods on that type I call the C functions. Works great.
How well does it work the other way round - calling Go from C/C++? IIRC when I first looked into doing that, it wasn’t really possible - only threads that were started by Go could run Go code. In particular, `main` had to be in Go and couldn’t be in C++. Does that restriction still apply?
I personally think Go's proposed implementation of parametric polymorphism a great feat of modern software engineering, and a testament to the open source process.
Anyway, they'll probably land in Go 1.18.
I don't actually think that's a bad thing: I love it that Google pays people to work on Go full time, and don't mind the language being spear-headed by a tight team with a vision (who happen to work at a commercial entity). I'm impressed with their direction, and ability to say no.
Personally, I'm opposed to adding generics, but if we have to...I trust the Go devs to do it better than just about anyone else.
Luckily I do have some ability to use C++ at my current job, so I can get my fix again there :)
It's the calm before the storm.
But I love that. :) 10 years in, Go is still my favorite language when it's the right tool for the job.
So actually, this is an exciting release IMO. Highlights:
- darwin/arm64 support (M1 chips)
- Go module quality-of-life improvements
- Built-in support for embedding files
- File system interface! (io/fs)
- Linker optimizations!
- io/ioutil -> io
- Lots of juicy crypto/* package improvements. Filippo and team are crushing it!