5 ms·
I have been developing in Go for several years and feel like I have seen most it can offer which is quite a lot for backend/networking systems. Besides its GC
by tomalaci 4y ago
I have been developing in Go for several years and feel like I have seen most it can offer which is quite a lot for backend/networking systems.
Besides its GC implementation that works very well most of the time, it also has simple but strong debugging tools to investigate how well you are handling memory allocation and CPU usage. Enforcing consistent coding style also makes it very easy to read other people's code and quickly contribute.
My suggestion to others is to avoid prematurely optimizing memory usage (e.g. trying to do zero-copy implementations) and always investigate performance via these profiling tools Go offers (e.g. pprof). Very often Golang's compiler or runtime will automatically optimize code that may not seem to allocate optimally.
There are still downsides but some of them are actively worked on:
1. Generics are still lack-luster (... but good enough to start replacing a lot of boilerplate code and will improve later on)
2. Error handling is still tedious (fortunately it seems to be their next big focus), it should take less code-space and have an option of stack-trace
3. Stdlib logging is too simple, lacks levels and structured-logging-style (currently actively discussed: https://github.com/golang/go/discussions/54763 https://github.com/golang/go/discussions/54763)
4. Low-level UDP networking is weak (soon to be fixed as they accepted this proposal: https://github.com/golang/go/issues/45886 https://github.com/golang/go/issues/45886 ), this will become more important as we transition to QUIC protocol
5. CGo (C interop / C FFI) is pretty bad performance-wise compared to other languages, it's OK if it is an I/O operation but anything C interop that requires low latency won't be running great
6. Similar to other languages, nowadays there are growing external dependency trees (e.g. I always wanted to use testcontainers-go to make integration tests easier but man, have you seen the dependency tree you will pull in with that pacakge?), solution in my eyes is flattening and standardizing most commonly used packages but Go in particular is very opinionated regarding what is included in stdlib
The above downsides mostly come from the background of creating distributed data pipelines and certain data collectors/parsers. For building API servers, I keep hearing it is a godsend in its simplicity, so your mileage may vary depending on the business domain you work in.
I would be interested to hear other people's experience with Go, however!
- Fire-Dragon-DoL 4y agoAnd don't forget, the plugin API has some super strong limitations. I wish that was fixed, otherwise platforms "similar to wordpress" can never become a thing on Go
- Xeoncross 4y agoPlugins for a compiled binary are just plain hard. Changing the code works better with an interpreted language. Usually you see the software implement it's own interpreter or a scripting language on top to handle this.
- Fire-Dragon-DoL 4y agoI know, I was thinking C# does something like that though, so I was hoping it would be achievable. The annoying part about the scripting language is that if something is written in Go, you want developers to also work in Go, otherwise the people writing plugins for your software, knowing better the API and use-cases, have a disconnection with the language actually used for the software, losing potential opportunities for contributions.
- int_19h 4y agoC# (usually) runs on top of a VM with a JIT, so the linking is effectively always done at runtime. It's also why it can do things like generic virtual methods - it can compile an instantiation and adjust the vtable at runtime.
- wahern 4y agoPlugins for ELF- and Mach-O-based systems aren't any different than regular shared libraries, modulo slightly different symbol precedence. AFAIU, while a quite different architecture, Windows PE linking treats them quite similarly, too. Perhaps you meant statically compiled binaries? Even then I'm not so sure about that. Right now I'm working on a project that statically compiles a plugin so its various libraries can't leak or be overridden by the loading application, yet which itself can load other plugins. OTOH, this is in C, C++, Objective-C, and Lua (basically C from the perspective of binary linking), all of which have mature linking semantics. (Well, at least this is true for C. Controlling symbol namespace pollution by C++ and Objective-C code requires more complexity than for C, but at least the necessary compiler and linker flags exist and are mature.) When you use languages or toolchains that don't invest in an ABI, or which make linking too automagic (with no or little recourse for exposing various linking features a platform may offer), then runtime linking is likely to become a major limitation in some solution areas. For example, there's probably no way to coax XCode to compile my plugins properly, without outsourcing some logic to additional scripts. Ultimately a Makefile is likely the best solution--and the one I chose, anticipating these headaches--as it keeps most of the build transparent. Fortunately, XCode seems to just be a wrapper around a bunch of command-line utilities, so you don't actually need XCode at all.