Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: reflect: permit setting struct methods/functions #31688

Closed
reisraff opened this issue Apr 25, 2019 · 4 comments
Closed

proposal: reflect: permit setting struct methods/functions #31688

reisraff opened this issue Apr 25, 2019 · 4 comments

Comments

@reisraff
Copy link

What version of Go are you using (go version)?

go version go1.11.5 linux/amd64

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOCACHE="/home/docker/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build140522671=/tmp/go-build -gno-record-gcc-switches"

What did you do?

package main

import (
	"fmt"
	"reflect"
)

type Foo struct {
}

func (Foo) Test() int {
	fmt.Println("original")
	return 0
}

func main() {
	mock := func(in []reflect.Value) []reflect.Value {
		fmt.Printf("false")
		return []reflect.Value{reflect.ValueOf(1).Elem()}
	}

	a := reflect.New(reflect.TypeOf(Foo{}))
	fmt.Printf("%v\n", a.Interface().(*Foo).Test())	

	fn := a.MethodByName("Test")
	v := reflect.MakeFunc(fn.Type(), mock)

	fmt.Printf("%v\n", fn.CanAddr())
	fmt.Printf("%v\n", fn.CanSet())

	fn.Set(v)
	
	fmt.Printf("%v\n", a.Interface().(*Foo).Test())	
}

https://play.golang.org/p/Onjw6KMe0gv

What did you expect to see?

I would like to propose the ability to set struct functions/methods. I know that #16522 is similar but is not the same, I want to override, and not add.

What did you see instead?

panic: reflect: reflect.Value.Set using unaddressable value

@ianlancetaylor ianlancetaylor changed the title Propose: with reflect be able to set struct methods/functions proposal: reflect: permit setting struct methods/functions Apr 26, 2019
@gopherbot gopherbot added this to the Proposal milestone Apr 26, 2019
@ianlancetaylor
Copy link
Contributor

In general the reflect package lets you do the kinds of things you can do in the language directly. But the language does not permit overriding the methods of an existing type.

@reisraff
Copy link
Author

My propose on this is create a mocker library for unit tests like we see in other languages.

An other way to do this is create a dummy struct that is composed by the aimed struct that should be mocked and so add methods/functions in order to override those child methods/functions

whould be awesome if one of these 2 approaches is implemented in the reflect pack.

@rsc
Copy link
Contributor

rsc commented May 7, 2019

In general it's not possible to do this to a running binary. Function calls have been inlined and otherwise are scattered all over the program, pre-resolved. There's no way to just jam in a new function in place of an existing one. Reflect is about looking at the program, not modifying it.

You may be interested to look at https://github.com/golang/mock, either to use directly or for inspiration.

@rsc rsc closed this as completed May 7, 2019
@reisraff
Copy link
Author

reisraff commented May 7, 2019

Ok thanks, I just made https://github.com/reisraff/mockings if someone is interested.

@golang golang locked and limited conversation to collaborators May 6, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants