On the technical side, Java and C# are OOP languages with nominal typing, compacting GCs (at least by default), objects are reference types, can't have a reference to a variable, strings are UTF-16, async is available via promises / tasks / futures, async scheduling is cooperative, and module boundaries are primarily type boundaries. Applications are typically shipped as platform-independent with a separate runtime. Interfaces are intrinsic to objects, from a runtime perspective. You can overload methods. Easy to dynamically load code at runtime.
Go has structural typing, non-compacting GCs, allows you to freely choose value / reference types, can make references to variables, strings are bytes or UTF-8, async is built-in to the runtime, async scheduling is preemptive, and module boundaries are defined by the package you’re in. Applications are typically shipped as native code with a linked-in runtime. Interfaces are extrinsic to objects, from a runtime perspective. You cannot overload functions. Hard to dynamically load code at runtime.
When I write it down like this, they don’t seem all that similar to me. They’re all… garbage collected and imperative? Memory safe (or mostly) by default? That doesn’t seem like a lot of commonalities.
“They are all used for backend programming” isn’t really that interesting because backend is where you can choose whatever language you want. Facebook has a ton of Hack backend, Jane Street has OCaML, etc.