redefine

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 5, 2026 License: MIT Imports: 12 Imported by: 0

README

redefine

Go Reference

Highly experimental package to redefine Go functions at runtime.

If you think you need this, you're almost certainly wrong. It exists because I wondered if were possible to redefine Go functions like some interpreted allow (Ruby, Perl, etc.).

package main

import (
	"fmt"
	"time"

	"github.com/pboyd/redefine"
)

func main() {
	redefine.Func(time.Now, func() time.Time {
		return time.Date(2000, 1, 1, 17, 0, 0, 0, time.FixedZone("somewhere", -5))
	})

	fmt.Printf("It's %s\n", time.Now().Format("3:04 PM MST"))
}

Outputs:

It's 5:00 PM somewhere

Documentation

Overview

Redefine Go functions at runtime

I wondered if it was possible to rewrite a Go function like some interpreted languages allow (Ruby being a prominent example). It turns out to be possible and this package is the proof-of-concept. You shouldn't use this.

Limitations:

  • Only supports amd64 on Unix or Linux
  • Relies on internal Go APIs that can break at any time
  • Silently fails to redefine inline functions
  • Silently fails to redefine generic functions
  • Probably some bugs I don't know about.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Func

func Func[T any](fn, newFn T) error

Func redefines fn with newFn. An error will be returned if fn or newFn are not function pointers.

Note that Func only modifies non-inlined functions. Anywhere that fn has been inlined will continue with the old behavior. If possible, add a noinline directive:

//go:noinline
func myfunc() {
	...
}

Other limitations that might be addressed one day:

  • Generic functions cannot be redefined
  • newFn cannot be a closure (anonymous functions are fine, but it will crash if you attempt to use data from the stack)
Example
package main

import (
	"fmt"
	"time"

	"github.com/pboyd/redefine"
)

func main() {
	redefine.Func(time.Now, func() time.Time {
		return time.Date(2000, 1, 1, 17, 0, 0, 0, time.FixedZone("somewhere", -5))
	})
	defer redefine.Restore(time.Now)

	fmt.Printf("It's %s\n", time.Now().Format("3:04 PM MST"))
}
Output:

It's 5:00 PM somewhere

func Method

func Method[T1, T2 any](fn T1, newFn T2) error

Method redefines a method of an object. The same caveats from Func apply here, with the new wrinkle that newFn must be a method on a type equivalent to the original type. For example:

type myCustomType otherpackage.Type

Any other type for the instance of newFn will likely lead to very troublesome bugs because the code compiled for newFn will be operating on the memory for the instance of fn.

Example
package main

import (
	"context"
	"fmt"
	"net"

	"github.com/pboyd/redefine"
)

type myResolver net.Resolver

func (*myResolver) LookupHost(context.Context, string) ([]string, error) {
	return []string{"127.0.0.1"}, nil
}

func main() {
	redefine.Method((*net.Resolver).LookupHost, (*myResolver).LookupHost)
	defer redefine.Restore((*net.Resolver).LookupHost)

	addrs, _ := net.DefaultResolver.LookupHost(context.Background(), "www.google.com")
	fmt.Printf("www.google.com has addresses %v", addrs)
}
Output:

www.google.com has addresses [127.0.0.1]

func Original

func Original[T any](fn T) T

Original returns a function with the same behavior as the original version of the function. If the function has not been redefined the original version if the passed function to that will be returned.

If the original function cannot be found for any reason Original returns nil.

Technically, this returns a copy of the original that's been relocated and had relative addresses adjusted. This process may introduce problems.

Example
package main

import (
	"encoding/json"
	"fmt"

	"github.com/pboyd/redefine"
)

func main() {
	redefine.Func(json.Marshal, func(v any) ([]byte, error) {
		// Pass strings through
		if _, ok := v.(string); ok {
			return redefine.Original(json.Marshal)(v)
		}

		return []byte(`{"nah": true}`), nil
	})
	defer redefine.Restore(json.Marshal)

	buf, _ := json.Marshal("A string")
	fmt.Println(string(buf))

	buf, _ = json.Marshal(123)
	fmt.Println(string(buf))
}
Output:

"A string"
{"nah": true}

func Restore

func Restore[T any](fn T) error

Restore reverses the effect of redefining a method.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL