Check out
github.com/davidthomas426/goconsole (I'm the author)
It's a project I work on for fun from sometimes. It is far from finished, but it's worth checking out. It relies very heavily on the reflect package to do its magic.
Restrictions that are intended, by design:
* no type declarations
* no function declarations like Go has at the top level
-> you just create variables of function type instead
* no imports *once the interpreter's already running*
-> instead, you can list packages when you start the interpreter, and it uses code generation and go run to bake them in.
* if you type in a deadlock, the interpreter deadlocks. I wanted the interpreter to be as close to the real runtime as possible, though this is admittedly perhaps less than ideal. Though, I'm not sure what I'd rather it do, and the design doesn't really allow anything else that I can think of.
Missing features because it's unfinished:
* panic/defer
* switch statements
* method calls (this one is major, of course)
* interpreted code is very slow and memory hungry
-> note that if you make calls to compiled code, that code is run natively. This makes the interpreter quite good at interactive glue code.
* errors of just about any kind cause log.Fatal, which means you lose all interpreter state. This of course is meant to be replaced with real error handling.
* various other language features that I haven't gotten around to implementing.
Particularly notable features that ARE there:
* goroutines (actual goroutines)
* channels
* select statements (turns into reflect.Select call with real communication ops, with correct semantics)
* Calling from interpreter code into native code (libraries)
* Calling from native code into interpreted code (think closures, I'll include an example below)
Here's my favorite example that actually works today, based on an example from net/http package docs:
$ goconsole net/http html log fmt
>>> http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
... fmt.Fprintf(w, "Hello, %q\n", html.EscapeString(r.URL.Path))
... })
>>> log.Fatal(http.ListenAndServe(":8080", nil))
(other terminal window)
I'll stop rambling. If you'd like to know more, let me know. I've always thought some interactive way to play with Go code would be nice, so I'm excited to see other people interesting in working on it.