1. We call set_function_lookup (line 30) so that libxml knows how to resolve function names. This stores a pointer to our interface as extra context for use by the callback.
2. When libxml sees an unknown function call in an xpath expression, it calls our C callback, go_resolve_function. (line 18)
3. We call our exported Go routine go_can_resolve_function to find out if the function name is registered.  (line 19)
4. go_can_resolve_function unpacks our interface and calls IsFunctionRegistered. (util.go)
5. If the function is registered, we tell libxml that it should call out generic callback exec_xpath_function, another exported Go routine. Otherwise, we return a null pointer so that libxml can continue trying to find a handler. (lines 20-22)
6. Assuming we have a registered function, libxml calls exec_xpath_function. (util.go)
7. We get the function name and our interface from the C context, call ResolveFunction on our interface to get the actual Go callback, then pop the arguments from the stack and invoke the Go callback. We take the returned value and push that onto the stack.

It's more convoluted than I'd like, but Go has limited flexibility when exporting C callbacks. If I could export a closure it would drastically simplify the flow.

For variables the control flow is much less convoluted, as libxml calls our exported function go_resolve_variable directly, which simply returns the value it gets from invoking the interface's ResolveVariable function.