Comments (3)
You took the red pill :)
It's a bit hidden in doc/features-and-limitations.md, that says:
- named types created by interpreted code are emulated. When the interpreter is asked to create for example
type Pair struct { A, B int }
, it actually creates the unnamed typestruct { A, B int }
. Everything works as it should within the interpreter, but extracting the struct and using it in compiled code reveals the difference.
This implies, although it's not written explicitly, that methods declared in interpreted code are emulated too, because it's not possible to declare methods on unnamed types.
If the type you created stays in the interpreter, it works as expected. But if you pass it to compiled code (and reflect.Value.NumMethod
is compiled code), the differences become visible.
There is no easy solution, because gomacro is a regular (although complex) Go program that uses reflection to create types, values, functions etc.: current Go reflect
package does not support declaring new named types, interfaces, and methods, so gomacro emulates them.
from gomacro.
What a pity ! Create a type with methods, instanciate and import it at runtime is my goal, but i believe that Go can do that. That's the first step to create Proxy instances from interfaces.
So as it's impossible with actual Go state, i close this issue.
from gomacro.
If your goal is to implement pre-existing interfaces at runtime, that's actually easier.
Gomacro supports that, and you can do it too in your code, even without an interpreter.
- using gomacro. Thanks to your question I just found a bug for methods on pointers. But it works if you define methods on values, as shown below:
package main
import (
"fmt"
"io"
"github.com/cosmos72/gomacro/fast"
)
const source = `
import "io"
type T struct { }
func (t T) Read(p []byte) (n int, err error) {
println("read called")
return 0, nil
}
func (t T) Write(p []byte) (n int, err error) {
println("write called")
return 0, nil
}
`
func main() {
it := fast.New()
it.Eval(source)
// you must explicitly instruct the interpreter to convert T{}
// into a io.ReadWriter
v, _ := it.Eval1("io.ReadWriter(T{})")
rw := v.Interface().(io.ReadWriter)
rw.Read(nil)
rw.Write(nil)
fmt.Printf("%+v\n", rw)
}
- do-it-yourself easy case: you know at compile-time which interfaces you want to implement at runtime. For example, let's say you want to implement
io.ReadWriter
at runtime, which has two methods:
interface {
Read(p []byte) (n int, err error)
Write(p []byte) (n int, err error)
}
Then you prepare a proxy struct that implements io.ReadWriter
and compile it in your code:
type Proxy_io_ReadWriter struct {
Obj interface{} // if needed by ReadFunc and WriteFunc below
ReadFunc func(Obj interface{}, buf []byte) (n int, err error) // this field is a function
WriteFunc func(Obj interface{}, buf []byte) (n int, err error) // this too
}
// declare the Read method matching io.ReadWriter signature
func (P *Proxy_io_ReadWriter) Read(buf []byte) (n int, err error) {
// forward the call to ReadFunc
return P.ReadFunc(P.Obj, buf);
}
// declare the Write method matching io.ReadWriter signature
func (P *Proxy_io_ReadWriter) Writebuf []byte) (n int, err error) {
// forward the call to WriteFunc
return P.WriteFunc(P.Obj, buf);
}
At runtime, it's just a matter of creating a Proxy_io_ReadWriter
, setting its fields, and storing it in a io.ReadWriter
- depending on your needs, you can do it either directly, or using the reflect
package. The code looks like this:
// something that returns a func(Obj interface{}, buf []byte) (n int, err error),
// maybe even by using reflect.MakeFunc() or a Go interpreter
readFunc := makeReadFunc()
// as above, something that returns a func(Obj interface{}, buf []byte) (n int, err error)
writeFunc := makeWriteFunc()
obj := makeObj() // if needed by readFunc and writeFunc
p := Proxy_io_ReadWriter{
Obj: obj,
ReadFunc: readFunc,
WriteFunc: writeFunc,
}
var rw io.ReadWriter = &p
- do-it-yourself difficult case: you know only at runtime which interfaces you want to implement. Then you need to create a .go source file containing the same proxy declaration as case 1) above, then compile it to a shared library with
go build -buildmode=plugin
, then load it with theplugin
package (only supported on Linux and Mac OS X), finally create and fill the proxy object as in case 1) above, but using reflection.
For completeness, gomacro uses both techniques 1) and 2) internally.
from gomacro.
Related Issues (20)
- I would like a full working example how to inject my application context(types and functions) in the REPL HOT 9
- Extract struct with methods from script to compiled code HOT 2
- Proxy can mix the called method of the imported structure HOT 3
- integrate with https://github.com/go-rod/rod HOT 2
- I'm unable to compile code importing gomacro on Mac OS m1 pro HOT 7
- Is there a way to Eval a folder HOT 5
- recursive type error cases: call of reflect.Value.Interface on zero Value HOT 6
- can't import fsm package HOT 4
- Different compilation behaviour from native go HOT 2
- undefined: pkgpath HOT 3
- Cannot convert struct to interface if it has an embedded struct with a method HOT 4
- Cannot import third party packages on Linux (not even the ones in the README) HOT 2
- Third-party imported type method is not callable from fast.Interp.Eval [gomacro repl works] HOT 4
- Idea for making adding third party packages to Gomacro easier when plugins aren't available HOT 3
- recursive type error cases: call of reflect.Value.Interface on zero Value
- can not import 3rd party packages HOT 13
- package <package> exports zero constants, functions, types, and variables HOT 3
- Caching of interp.Eval1 results HOT 13
- Way to disable go get import and enforce to use only defined import list HOT 3
- An error will be reported when using third-party packages on Windows HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from gomacro.