Good benchmarks, but what you are seeing are the consequences of the fact that Go's `regexp` engine isn't very optimized, it implements a fairly naive NFA-based regular expression engine. This is perfectly reasonable for simple use cases like input validation or parsing simple string formats, it's plenty fast in that case. When you throw a complex regex with backtracking you can see performance drop severely compared to other engines. If you throw a regular expression that does not have backtracking or case insensitive literals it performs reasonably well and executes it in one pass as you'd hope.
Of course if you were writing something like grep where the throughput is directly tied to regexp execution, yes, you would most certainly want to pick an optimized regexp engine, though it would likely come at the cost of needing a JIT and other complexity.
The existence of `regexp` in the standard library, though, certainly doesn't stop you from picking a more optimal library, any less than it does for JSON parsing for example.
> Nothing that Go has is uniquely better or even competitive. Both C# and Java have way more extensive and optimized standard libraries.
I think that it is very nice when standard libraries contain "optimal" implementations of things, but in most cases it's not the most important concern. Having sufficient implementations of things is much more important. And in that regard, Java is far from the worst, but it's also far from the best, too. For the longest time, Apache Commons was treated as a defacto-standard library for Java programs, I'm sure you've experienced this. Most of the stuff in Apache Commons is stuff you can also find built-in to Go.
> What Java has working against it is the lack of structs, monomorhpized generics and SIMD API to ensure all standard library bits stay as performant as they are in .NET, but nonetheless the areas that have no use of those are optimized to a comparable degree.
Honestly, Java's performance was never that bad, it is/was specific things that really caused it to suck, like objects, reflection, the GC. Some of it has been improved greatly, in part thanks to ZGC and other innovations, but Hotspot was always pretty good at running tight loops and computations at a respectable speed.
What makes Go nice is that it just doesn't need as much optimization to begin with. It's funny to compare Go code to highly complex and optimized code all of the time, but this happens mainly because it still often competes in the same class despite being kind of dumb and simple by comparison, for a myriad of reasons. The Go GC is probably technically not as optimal as the latest and greatest Java technology, but it doesn't really matter too much because Go manages to do a better job at preventing objects from escaping to the heap in the first place. Java is recently getting on this train, too, but it's got a long road ahead, as Java code and interfaces will need to be adjusted to try to minimize unnecessary escaping to fully exploit this. A lot of common Java patterns don't make this easy.
> And you can be sure they offer sufficiently good support on all major platforms: Linux, macOS, Windows and, what is a major Java/Kotlin's advantage, Android. Something that Go treats with pretending like the only platforms that exist is UNIX/POSIX.
What is wrong with Go's support of Windows or Android? I use Go for Windows programming all the time. I was even working on writing a Win32 language projection for it, but I lost a bit of the code and haven't had time to pick it back up. Go ends up being nice to use with native Windows APIs especially since you can dynamically link to libraries without needing CGo.
Meanwhile, Java programs seem to have a harder time dealing with platform interoperability than Go programs. For example, ANTLR4 still seems to have issues handling paths with backslashes: they work, but the relative path calculations that are done are wrong, resulting in different behavior/output. I choose this as an example because it's a really popular and not particularly new Java program, but it's also the latest iteration, showing that Java platform interoperability issues are nothing new. It's, of course, not Java's fault that Java programs may contain bugs; but it is Go's work that has made it less likely for Go programs to make this mistake by designing the standard library to make path manipulation straight-forward whether you want to deal with OS-specific paths (`path/filepath`) or slash-only paths used in URIs (`path`).
> And for interpreting AST, this exists in both Java and C# with different strategies. C# approach is a bit more complex but extremely powerful with build-time source generators that have full access to AST generate new code, fill out existing partial members or intercept calls, and does not require any external scripting. A good example of that is generating gRPC clients and servers code from .proto file by simply executing `dotnet add package Grpc.Tools` and adding .proto reference to .csproj.
gRPC code generation is reading from protobuf descriptors, not modifying existing C# code. It's cool that C# has a good interface for printing C# code, but it's kind of not what I was getting at with that.
And of course, it's obviously still possible to parse the grammar into an AST in Java or C# or C++ or ... but the advantage for Go is that yeah, the grammar is simple and has a lot fewer productions and a lot less syntax than pretty much all of those. That means that mere mortals can write their own refactoring tools, and often do.
With Go's syntax being so dumb, it's possible to just generate proper Go code with text templates, which is what a surprising amount of Go code gen does. It's not especially fragile because the syntax has rather few surprises and once you know them it's not very challenging to follow the rules completely using only simple string operations. (You can also, of course, fill out an AST and write it too, using `go/printer`.)
> Go may seem like a good language after coming from scripting nightmares, it may even seem like a good systems programming language that is easy to use. I promise, it is not. In order to call intrinsics, in C#, I just call them because that's what it offers, in Go, I have to write asm helpers manually.
> If you look at what modern C#, Kotlin and, again, Rust provide in their respective areas, you will soon realize that Go does not have anything to offer that is unique or better, except perhaps the culture of minimalism, which other ecosystems are also advocating for in at least last 5 years.
I disagree. I am not particularly new to programming, and I have come to the conclusion that Go is a great programming language for productivity, as it strikes a nice balance in a lot of aspects of programming language design. I also am not trying to suggest that there are no virtues of C# or Rust, either, just that it's especially weird how much of a hate-boner Go has. It's not like liking it is particularly popular anymore, trust me, as a person that likes Go I would know, so you'd think the irrational hatred of Go would end. Alas, it continues, to the point where there's somehow an argument here that unlike basically every other programming language that has ever existed, somehow Go is the one with zero merits at all. That's pretty much what it feels like I'm arguing against right now, FWIW.
... This comment was too long, so I'm going to need to reply to the rest in a different post ...