Passing byte array to plugin function - go

I need to write a golang plugin with a function that accepts an array of golang bytes, but when I try to call this function after loading the plugin in the client code, it always gives me
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x40b22af]
Any suggestions on how to resolve this?
code to reproduce(highly simplified, but the same error occurs)
client.go
package main
import (
"plugin"
"log"
)
type T interface {
sayHi(data []byte)
}
func main() {
plgin, _ := plugin.Open("./plugin.so")
symbol, _ := plgin.Lookup("Endpoint")
b, _ := symbol.(T)
log.Println("From main")
data := []byte{1,2,3,4,5}
b.sayHi(data)
}
plugin.go(this program is built with buildmode=plugin)
package main
import (
"log"
)
type dummy struct {}
func (d dummy)sayHi(data []byte) {
log.Println("From plugin")
log.Println(data)
}
var Endpoint dummy
func main() {
}

First, you should always check returned errors (and the result of type assertion from the plugin symbol)!
The problem in your case is that the sayHi() method is unexported. So if you create an interface in your app, it will not match the unexported method created in the plugin.
Export the method, and it will work (given you don't get any other errors).
In the plugin:
func (d dummy) SayHi(data []byte) {
log.Println("From plugin")
log.Println(data)
}
In your main app:
type T interface {
SayHi(data []byte)
}
And when calling it:
b.SayHi(data)
One thing to note here. When you lookup a variable from a plugin, you get a pointer to the variable (else you could not change its value). For details, see: Plugin symbol as function return. What this means is that symbol will be of type *dummy, not dummy. This doesn't cause any troubles here, as the method set of *dummy also contains the SayHi() method, just like the method set of dummy, but you should not forget about this if you would attempt to type-assert a non-interface type (a concrete type) out of a plugin symbol.

Related

Context value is nil when getting it with unexported struct key in Go HTTP handlers

Any help here is appreciated! I'm sure that I'm missing something really basic.
The problem I have is I am trying to get a value out of context in a demo web application, and I'm receiving the error:
2021/04/11 11:35:54 http: panic serving [::1]:60769: interface conversion: interface {} is nil, not []string
In my main function I'm setting the context with the following:
package main
type ctxKey struct{}
func someHttpHandleFunc() {
// .....
ctx := context.WithValue(r.Context, ctxKey{}, matches[1:])
route.handle(w, r.WithContext(ctx))
}
Then in my handler, I have the following:
package some_package
type ctxKey struct{}
func getField(r *http.Request, index int) string {
fields := r.Context().Value(ctxKey{}).([]string)
return fields[index]
}
I know that I'm missing something simple because if I try the above code and put my getField() function within the package main everything works.
For reference, this is a learning exercise, I'm trying to teach myself Go routing. I do know that there are routing packages available - but my goal is to learn. I'm trying my best to follow along with Different approaches to HTTP routing in Go. I have also read through Pitfalls of context values and how to avoid or mitigate them in Go. The latter seems to directly address the problem I'm having, but I can't seem to figure out how to solve it based on what is there.
Defined struct types defined in different packages are different.
package main
type ctxKey struct{}
is not the same type as
package some_package
type ctxKey struct{}
To make it intuitively clearer, think that if you were to reference these types from a third package — let's pretend the types were exported — you would have to import the corresponding package and use the appropriate selector:
package baz
import (
"myproject/foo"
"myproject/some_package"
)
func doBaz() {
foo := foo.CtxKey{}
bar := some_package.CtxKey{}
}
Now, the implementation of Value(key interface{}) uses the comparison operator == to determine whether the supplied key matches:
func (c *valueCtx) Value(key interface{}) interface{} {
if c.key == key {
return c.val
}
// then it checks if the key exists on the parent
return c.Context.Value(key)
}
Which implies that the types also must match. From the specs, comparison operators
In any comparison, the first operand must be assignable to the type of the second operand, or vice versa.
And clearly in your example ctxKey struct{} declared in main is not assignable to ctxKey struct{} declared in some_package, and vice-versa, because their types differ.
To solve your error, make sure the keys used when setting and getting the context value are the same type. The best way, also to ensure proper encapsulation, would probably be to set and get the context value from the same package:
package some_ctx_helper_pkg
// unexported, to ensure encapsulation
type ctxKey struct{}
func Set(ctx context.Context, value interface{}) context.Context {
return context.WithValue(ctx, ctxKey{}, value)
}
func Get(ctx context.Context) interface{} {
return ctx.Value(ctxKey{})
}

Uninitialized Embedded Struct

I'm a bit perplexed by this go code. I have a struct (Outer) with an embedded struct (Inner), but when I initialize Outer, I intentionally leave the embedded struct uninitialized.
type Inner struct {
value int
}
func (i *Inner) MyFunc() string {
return "inner"
}
func (i *Inner) OnlyInner() string {
return "only inner stuff"
}
type Outer struct {
*Inner
}
func (o *Outer) MyFunc() string {
return "outer"
}
func main() {
// embedded struct is *not* initialized
o := &Outer{}
fmt.Println(o.Inner)
fmt.Println(o.Inner.MyFunc())
fmt.Println(o.Inner.OnlyInner())
//fmt.Println(o.Inner.value)
}
Output:
<nil>
inner
only inner stuff
And if I uncomment the last line (with o.Inner.value), I get a nil pointer dereference error.
What's up here? The effective go page says (https://golang.org/doc/effective_go.html#embedding):
When we embed a type, the methods of that type become methods of the outer type, but when they are invoked the receiver of the method is the inner type, not the outer one.
It seems like in my case, the inner type is <nil>, yet the method calls execute without problem. What's going on under the hood?
A method can be called with a nil receiver, as long as you do not dereference the receiver itself.
This means that the following works playground:
package main
import (
"fmt"
)
type foo struct {
val int
}
func (f *foo) Print() {
fmt.Println("Receiver:", f)
}
func (f *foo) PrintVal() {
fmt.Println("Val: ", f.val)
}
func main() {
var f *foo
f.Print()
//f.PrintVal()
}
f.Print() works without issues since we're just printing a pointer, we're not trying to dereference it.
However, f.PrintVal attempts to dereference a nil pointer, causing a panic.
When in doubt, remember that the methods in this example are equivalent to functions that take the receiver as first parameter:
func Print(f *foo)
func PrintVal(f *foo)
This is mentioned in the spec under method declarations:
The type of a method is the type of a function with the receiver as
first argument. For instance, the method Scale has type
func(p *Point, factor float64)
However, a function declared this way
is not a method.
This makes it clear that the receiver is nothing special, it can be nil as long as you don't dereference it.
The methods of the uninitialized struct are being called with a nil-receiver. If in the methods used that receiver you would get a panic. It is valid to call a method using a nil receiver, and the method could modify its behavior by checking if the receiver is nil.

Struct embedding of interfaces, panic: runtime error

I'm trying an example related to struct embedding of interfaces
// https://talks.golang.org/2014/go4java.slide#52
// Struct embedding of interfaces
// https://play.golang.org/p/SYiZ7M1OEhU
package main
import (
"bytes"
"fmt"
"net"
)
// net.Conn has Read and Write
type loopBack struct {
net.Conn
buf bytes.Buffer
}
func (c *loopBack) Read(b []byte) (int, error) {
fmt.Println("loopBack Read")
return 0, nil
}
func main() {
loop := loopBack{}
loop.Read(nil)
loop.Write(nil)
}
and the Write method is undefined, so I get this runtime error
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0xffffffff addr=0x0 pc=0xe28ca]
goroutine 1 [running]:
main.main()
/tmp/sandbox812386031/main.go:28 +0x6a
Exist some way to validate it at compile time?
link to code
https://play.golang.org/p/SYiZ7M1OEhU
What you are doing is not the same as saying "loopBack implements net.Conn".
To get compile-time error(s) about the missing method – and the mismatched Read(), too – declare loop's type:
(And don't embed net.Conn in loopBack)
func main() {
var loop net.Conn = loopBack{}
Golang doesn't require exlicit interface implementations. What you do here:
type loopBack struct {
net.Conn
buf bytes.Buffer
}
Is the similar to:
type loopBack struct{
Conn net.Conn
buf bytes.Buffer
}
net.Conn being an interface type, the first field of your loopBack type can be anything that implements the net.Conn interface, which is of course more than Read and Write alone (see here).
The advantage of embedding types is that the fields and receiver functions (name conflicts aside) can be accessed directly on the types that embeds them.
With an embedded net.Conn field, you can indeed write:
loop.Write(nil)
If the Conn field is initialised (otherwise, its value is nil). Changing the declaration to the second version, loop.Write won't work, you'll have to write:
loop.Conn.Write(nil)
Type embedding is very powerful, but there's a number of gotcha's when you first get started. Thankfully, there's an entire paragraph explaining embedding on the effective go doc
Anyway, as stated, you are able to call functions, and access fields (if you're embedding a struct type instead of an interface). There is one thing, though: the field must be initialised correctly!
And that's where you went wrong: You still have to initialise your Conn part of the loopBack variable, otherwise what you're doing is the same as:
net.Conn(nil).Write(nil)
Which, naturally, results in a panic (nil pointer dereference)...
For example:
conn, err := net.Dial("tcp", "localhost:80")
if err != nil {
log.Fatalf("failed to dial localhost: %+v", err)
}
loop := loopBack{
Conn: conn,
}
loop.Write(nil) // same as conn.Write(nil)
Failing to set the net.Conn embedded field is akin to doing something like this:
s := make([]*int, 10) // make slice of 10 pointers to int
fmt.Println(len(s)) // outputs 10
*s[0]++ // add 1 to first element PANICS
The 10 elements in the slice exist, but they've all been initialised to nil

How HandlerFunc(f) convert a function to an interface type?

When check following code, got a doubt with type convert from function to interface.
Code
http_hello.go:
package main
import (
"fmt"
"log"
"net/http"
)
// hello http,
func helloHttp() {
// register handler,
http.Handle("/", http.HandlerFunc(helloHandler))
// start server,
err := http.ListenAndServe(":9090", nil)
if err != nil {
log.Fatal("ListenAndServe:", err)
}
}
// handler function - hello,
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, you've requested: %s\n", r.URL.Path)
}
func main() {
helloHttp()
}
The above code works.
(Then I tried to write a small program to check is this a general feature, but it won't work, check following code)
func_to_intf.go:
package main
import (
"fmt"
)
// an interface,
type Adder interface {
add(a, b int) int
}
// alias of a function signature,
type AdderFunc func(int, int) int
// a simple add function,
func simpleAdd(a, b int) int {
return a + b
}
// call Adder interface to perform add,
func doAdd(a, b int, f Adder) int {
return f.add(a, b)
}
func funcToIntf() {
fa := AdderFunc(simpleAdd)
fmt.Printf("%#v, type: %T\n", fa, fa)
a, b := 1, 2
sum := doAdd(a, b, fa)
fmt.Printf("%d + %d = %d\n", a, b, sum)
}
func main() {
funcToIntf()
}
Output:
./func_to_intf.go:30:14: cannot use fa (type AdderFunc) as type Adder
in argument to doAdd: AdderFunc does not implement Adder (missing add
method)
Questions
http.HandlerFunc(helloHandler) get a value of type http.Handler, since that's what http.Handle() expect, is that correct?
If yes, then means it convert a function into a value of an interface type, how did that happen?
Is this a built-in feature of go?
I did a test (as in func_to_intf.go above), and seems not.
Or, is http.HandlerFunc's special implementation achieve that?
#Update - Summary
(Though the answer(s) addressed the questions pretty well, but after reviewing & more testing, there are several other go features required to totally erase the original doubt, as following.)
Function type.
Function is value, and it has type.
Function type could be defined via type keyword on a function signature.
e.g type AdderFunc func(int, int) int
Type convertor T(v) on function.
Any function could be converted to a function type with the same signature, just via T(v), use function type name as T, and actual function as v.
Then when the new value is called, the actual function v is called.
e.g fa := AdderFunc(simpleAdd)
(this is blur to me before asking the question, and that's one of the main reason I was confused).
It is a simple type-conversion.
In Go you can define custom type besides structs. In this case, http.HandlerFunc is a function type, func(http.ResponseWriter,*http.Request). Since your function is of the same underlying type (signature) as the custom type, it can be converted to it.
Furthermore, code can define methods on custom type, no matter what underlying type it is, or whether it is a struct or not. In this case, http package defines ServeHTTP method on it, and of course, it just calls the function itself.
You can read the source code here: https://golang.org/src/net/http/server.go?s=58384:58444#L1936
As for the adder in your sample code, you can do the same: Define a method on AdderFunc.
func (a AdderFunc) add(x, y int) int {
return a(x, y)
}
Playground: https://play.golang.org/p/5mf_afHLQA2
http.HandlerFunc is a type that satisfy interface http.Handler by providing method http.ServeHTTP(ResponseWriter, *Request).
http.HandlerFunc(helloHandler) is a type conversion which convert types with same underlying base type but different method set.
You example working
Not special or built-in feature. Instead http.HandlerFunc is a type that implements the http.Handler interface. Have a look at its implementation which is quite nifty https://github.com/golang/go/blob/d3c3aaa61f7598f275f30fabd3749379fe0f2720/src/net/http/server.go#L1956
As the docs say:
The HandlerFunc type is an adapter to allow the use of ordinary functions as HTTP handlers. If f is a function with the appropriate signature, HandlerFunc(f) is a Handler that calls f.
So, it's not a function, but a wrapper type, declared as:
type HandlerFunc func(ResponseWriter, *Request)
But Go allows (and that's one of its greatest features, in my opinion) to make any newly declared type implement any possible interface just by defining the require method. So the type HandlerFunc implements the interface Handler by defining the method ServeHttp. The implementation just calls the wrapped function.

Why a type assertion works in one case, not in another?

Here is the problematic source code:
http://play.golang.org/p/lcN4Osdkgs
package main
import(
"net/url"
"io"
"strings"
)
func main(){
v := url.Values{"key": {"Value"}, "id": {"123"}}
body := strings.NewReader(v.Encode())
_ = proxy(body)
// this work
//invalid type assertion: body.(io.ReadCloser) (non-interface type *strings.Reader on left)
_, _ = body.(io.ReadCloser)
}
func proxy( body io.Reader) error{
_, _ = body.(io.ReadCloser)
return nil
}
Can someone tell me why this code wont work ?
The error occur here:
body := strings.NewReader(v.Encode())
rc, ok := body.(io.ReadCloser)
// invalid type assertion: body.(io.ReadCloser) (non-interface type *strings.Reader on left)
However proxy(body io.Reader) do the same thing but have no error. Why?
http://play.golang.org/p/CWd-zMlrAZ
You are dealing with two different Reader:
strings.NewReader() returns a strings.Reader, which isn't an interface.
But since it implements io.Reader, you can pass it to proxy().
proxy() takes an io.Reader, which is an interface.
For non-interface types, the dynamic type is always the static type.
A type assertion works for interfaces only, which can have arbitrary underlying type.
(see my answer on interface, and "Go: Named type assertions and conversions")

Resources