There's not much difference between Go and the JVM, except one is compiled just in time and the other ahead of time. There's also been a few ahead of time compilers for Java over the years, with substrateVM being the latest one for example.
From https://golang.org/doc/faq they say:
> Go does have an extensive library, called the runtime, that is part of every Go program. The runtime library implements garbage collection, concurrency, stack management, and other critical features of the Go language
I think people can argue all they want about semantics, what is a virtual machine? There are not "proper definition" for this. Ultimately, if you abstract away the details of the running environment, to me, you've created a virtual machine.
The Go FAQ continues by insinuating it isn't a virtual machine because it doesn't do just in time compilation and only ahead of time. I think that's just word play.
From https://en.m.wikipedia.org/wiki/Virtual_machine says:
> A process VM, sometimes called an application virtual machine, or Managed Runtime Environment (MRE), runs as a normal application inside a host OS and supports a single process. It is created when that process is started and destroyed when it exits. Its purpose is to provide a platform-independent programming environment that abstracts away details of the underlying hardware or operating system and allows a program to execute in the same way on any platform.
Personally, I think "Managed Runtime Environment" is a better term, and Go would definitely fall into that term.
So I recognize the difference are real. Just in time Vs ahead of time. But it isn't docker, or any other layer of virtualization which magically allow Go to run over many machines. Its because it has an extensive runtime that abstracts away their details. And this runtime has to be bundled in every compiled application. Maybe we should start talking about virtual runtimes?