Interpreting Go is a good idea. In fact, a JIT for Go would be a very interesting idea as well. In a language that makes heavy use of virtual dispatch like Go does (via interfaces), you can often get a lot of mileage out of speculative devirtualization. With a JIT you can easily observe the concrete types that flow through each call site, allowing for optimizations you can't easily do with AOT compilation (without PGO, anyway). You can even do aggressive optimizations like observing that only one type that's currently loaded in the program conforms to an interface and devirtualize accordingly, knowing that you can undo that optimization if more code gets loaded later on that invalidates this assumption.
I would like to call interpreted Go code from compiled Go code, say, like: run("dynamic.goi"). Would I be able to call back into the compiled code from the interpreted code? Can the two parts share variable state?
Exposing an "FFI" is definitely a step along the way in any project like this, though I've never personally found it particularly straightforward (or fun). It does open up the floodgates for functionality though.
Like the sibling mentions, yaegi seems to do that today (though I haven't used it).
The method I wrote about doesn't seem particularly any more conducive to making a REPL than progressively building a valid Go program with each line and compiling/running that (since Go's compiler is very fast).
However, there may be some benefits to prototyping in an environment like this where you can ignore types for a bit.