C++ and Go are designed to compile to native machine code. Both have a phase during building where separate modules are linked together to produce a single combined module. Once this has been done, a complete list of all available objects is available. Therefore, the easiest way to initialise any object that requires initialisation is to scan that list, check for init code, and call it (there may be slightly more subtlety to it than that, but as a broad conceptual level it's close enough to how it works for the purposes of this discussion).
Java and C# were both designed to run in a virtual machine environment. Java specifically was designed to perform on-demand loading of code. Linkage is deferred until runtime in order to allow, for example, modules to reside on a remote server where they may be updated without changing the remaining program (this is important for Java's original designed purpose, which was for writing applications for smart tv systems). Furthermore, classes may be added to the system at runtime (using Class.forName). This means that it is impossible for a Java application to determine a complete list of all classes it may use at build time, or even when the application begins running. Therefore it is impossible for Java to perform initialisation at application start.
C#, AFAIK, had a design goal that it needed to be able to be used for any kind of application where Java could already be used. It therefore needed to follow Java's lead in using on-demand loading, even though it does have a separate link step, because not doing so would make it hard to support network-loaded applications.