I am working on a type of Go preprocessor that rewrites source code to add 
additional instrumentation to certain types of statements.

One such statement is the go statement. I would like to instrument the 
newly created goroutine, injecting some instrumentation code at the start 
and finish of the goroutine.

In the simple case, the rewrite is straightforward:

go fn()


go func() {
defer instrument()()

However this approach does not work when fn takes parameters.
If we were to rewrite go fn(expr) into the equivalent form above:

go func() {
defer instrument()()

the semantics change, since in the rewrite expr gets evaluated inside the 
newly created goroutine, which can change the behavior and introduce data 

My attempts to address this have not been particularly fruitful.

One cannot pass in expr as an argument to the closure, because the type of 
the expression may not have a valid name in the current package (for 
example if expr evaluates to a private type in some other package). 

Similarly, if expr is a constant expression (like 1 or nil) the type may 
depend on the corresponding parameter in fn’s signature.

The only semantics-preserving rewrite I can think of revolves around using 
package reflect, and rewriting like so:

go func(fn reflect.Value, vals …reflect.Value) {
defer instrument()
}(reflect.ValueOf(fn), reflect.ValueOf(expr))

As far as I understand, this should be semantics-preserving, although with 
a slight performance cost. (Though I imagine the cost of a reflection-based 
call is dwarfed by the cost of spawning a goroutine.)

Unfortunately this also comes with a major downside: the rewritten code 
does not typecheck identically to the original code. Ideally I would like 
the rewritten form to cause identical typechecking failures to the old 
code, so that these errors are caught at compile time without requiring a 
separate typechecking pass for the original code.

Am I correct in the above reasoning? Can anyone think of a way to do this 
sort of rewrite in a semantics-preserving and typechecking-preserving way?  

You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 

Reply via email to