Hacker News new | ask | show | jobs
by umvi 1764 days ago
At first I didn't like Go because I thought it was too opinionated. But the more I used it, the more I found the tooling to be just heads and shoulders above similar languages like C/C++.

I use VSCode a lot, and in VSCode you can press "F12" to jump to the location of a function definition. In Go I find myself deep diving into github libraries all the time just because F12 takes me there. That never happened with C/C++ - the tooling was just too disparate and fragile.

My biggest complaint with Go is lack of generics. I mean technically you can achieve generics with an unholy empty interface/reflection incantation but it's a huge pain compared to C++.

9 comments

I think people claiming modern C/C++ tools are close to as good as Go’s are wrong, in my opinion. With that having been said, IMO if you want the C++ experience to be better, use Clangd and generate a compile_commands.json file. For many projects you can use wrappers like compiledb, or Bear, and some build systems like CMake can output it natively. Either way, once you have found a way to do this, and get it outputting into the project root, add a local ignore for it (in .git/info/exclude) and install the VSCode clangd extension.

Truly, it is night and day. I can get Real code intelligence on almost anything, including large C projects with custom Makefiles that compile cross-arch like Wine. It only ever has trouble with unusual translation unit patterns. (You can see this in Higan for example, which has .cpp files including other .cpp files; clangd seemingly fails to put them in the context of the intended translation unit.)

It’s not as good as Go, but it is life-changing for me.

If you use C++ tools where your dependencies get pulled in and built from source like Go does, you get the same experience. If you only have prebuilt system libraries obviously this doesn't work.

It's not like Go's tooling is that much better than the best modern C++ tools, but the ecosystem is so much more unified by having 1 blessed set of tooling. Rather than 20 different package managers/(meta)build systems. No need to worry that I am using build system X, but I want to use a library using build system Y.

In C++, preprocessor and template magic in dependencies tends to break such IDE convenience features as "go to definition" or "find all references".
This almost doesn't happen when your tools are good. At Google the Kythe tool (https://kythe.io) gracefully deals with templates, macros, and much more. Both "go to definition" and "find references" just work with 99.9% of C++ code, including within complicated macros and templates.

(The one and only case I've ever found it doesn't work is to find references to a function that's only called via ADL in a widely used template that's instantiated with thousands of different types.)

What about SFINAE?
Works. Because it uses the compiler to figure out what calls what, and so the compiler has already selected the right overload.
tbh I've had dramatically worse type-aware IDE features with Go than almost any other mainstream language. gopls routinely misses trivial things in the same file. Goland does substantially better, but it still has major problems gathering a complete call hierarchy, and basic things like moving a file to a different package (with no compilation issues, just import rewrites) still don't work reliably.
Generics are hopefully coming February 2022 with 1.18.
Important note: it's the preview release. Not everything will be done, there will be gaps. But the first parts of the work have already merged to master, and it's coming.
This will be when I finally use Go for something then.
Even with generics, it has so many issues:

* Error handling is error prone and awkward.

* No proper enums

* No sum types/pattern matching

* Null pointers exist

* Its interfaces are very awkward. There are superior implementations of what they tried to do in other languages.

* Subpar IDE experience, made worse by how interfaces are implemented. You need an IDE for any non-trivial project.

* Very awkward choice to have visibility be determined by the case of the first letter in the function or variable. Simple changing of visibility to public will require larger diffs if it's used a lot.

* No private visibility, only package private.

* Very crude import mechanism. Try to rename a package and see how the IDE fails to figure out what to change.

Funny, I've only ever used vim for go projects big and small, and the experience was excellent

Wouldn't any visibility change require a large diff in all languages?

Have you tried "F2" (rename symbol)? It's amazing, it's like a "safe" find & replace all.
Yes, I've been using F12 a lot too, just to dive into random projects. It's amazing how much this little feature means.
Cross-platform Intellisense support in VSCode with the Microsoft C/C++ extension has improved a lot lately, especially in combination with the CMake Tool extension to automatically discover header search paths and other compilation settings (it used to be very brittle in the beginning on Linux and Mac).

But if you're coding C/C++ in a "proper" IDE like Visual Studio, CLion or Xcode, such features are expected to work out of the box. IME, Intellisense-like features are usually only a pain to setup in "non-integated" development environments like Vim or other text editors.

If your reference point is C/C++ then sure.. Go is a progress, but give more modern languages a try, like Kotlin, they sure are a major ergonomic and featureful evolution over go
That's the sad truth. Go is not leap and bound better on that front, it is C/C++ that has not catched up.
"you can press "F12" to jump to the location of a function definition" Seems like standard IDE functionality for at least 20 years.
This is more a limitation of VSCode than C++. Go to Definition for C++ works just fine in Visual Studio proper for many years now.