got reload?
Function/method-level stateful hot reloading for Go!
Status
Very much work in progress. The usage of this tool changes pretty much daily
as we iterate on it. That being said, it is usually usable for some definition
of "usable."
Do you have a demo?
Clone this repo somewhere and do the following within the repo's root directory:
go run ./cmd/got-reload run -p github.com/got-reload/got-reload/demo/example ./demo/
In a different terminal, return to the original cloned repo and edit one of
the function definitions in demo/example
or demo/example2
. For starters,
just make it return a different constant.
You should see the running program discover the changes and reload the definition
of the function. Press enter a few more times to watch the return value change.
Note how the package-level variable's state was not reset by the reload.
You can also try our Gio-based GUI live editing demo:
go run ./cmd/got-reload run -p github.com/got-reload/got-reload/giodemo/reloadable ./giodemo/
Try altering the layout function defined in ./giodemo/reloadable/reloadable.go
. See the comments for ideas.
Inspiration
See this video that Chris did for something similar:
https://user-images.githubusercontent.com/2324697/106301108-4e2fce80-6225-11eb-8038-1d726b3eb269.mp4
How it works
Rewrite each function/method
We alter each function and method declaration in your code so that it invokes
a package-level function variable. This allows us to redefine the implementation
of your functions/methods at runtime.
The filter will transparently change functions from this
func Foo(... args ...) (...return values...) {
}
into this
func Foo(... args ...) (...return values...) {
return GRLf_Foo(...args...)
}
var GRLf_Foo = func(...args...) (...return values...) {
}
func GRLset_Foo(f func(...Foo's signature)...) {
GRLf_Foo = f
}
and similarly for methods.
Export all named private package-level variables, types, interfaces, and
struct field names, by adding "GRL_" to the front.
(None of this is done in-place, it's all performed on a temporary copy of the
packages being filtered. No original source code is changed.)
We watch your source for changes at runtime
When a filtered source file changes, it will be read, parsed, and changed
functions will be installed with new versions of themselves via the generated
GRLset_*
functions, via Yaegi, a Go
interpreter.
Limitations
Who came up with this harebrained idea?
Given that Yaegi's been out for a while, and Go's parsing tools have been out
since the beginning (well, a lot of them, anyway), we both wonder why nobody
has done this yet, to be honest.
Can I use it now?
Yes? Kinda depends on your tolerance for jank and breaking changes. If you can
survive the fact that the CLI may change on a daily basis, then sure!
Can I support the development of this tool?
Yes! We appreciate stars, watchers, feedback, and, of course, pull requests! A PR need not necessarily be code, of course; it could be documentation, or something else. Whatever itch you care to scratch.
You can also sponsor the developers: