Is it possible that use some func to do the same thing like that the Lookup() does in go-plugin

As we Know we can use Lookup func to get a func’s callable type in a plugin,such as:

targetFunc, err := pluginFile.Lookup("PrintNowTime")

so is it possible do the samething without plugin?

ps: I don’t want to use map or something else must be wrote in code. I want to get function’s string name by mysql and then use Lookup() to find the func

You can’t do this in Go. The compiler can omit functions that aren’t referenced in the code, for example, given:

package main

import "fmt"

func main() {
  fmt.Println("test")
}

func MyFunc(a, b int) int { return a + b }

type MyType struct{ S string }

MyFunc and MyType might not exist in the compiled binary because neither are ever referenced. This is why Go doesn’t offer things like looking up types by their names from the reflect package; you can only get exported member functions of a type via the reflect package if the code you build references that type somewhere; that’s the only way to be sure that the compiler included the type at all.

The way around this is to build a map yourself of the functionality you need:

package main

import "fmt"

func main() {
  fmt.Println(myMap)
}

var myMap = map[string]interface{}{
  "MyFunc": MyFunc,
  "MyType": reflect.TypeOf(MyType{}),
}

func MyFunc(a, b int) int { return a + b }

type MyType struct{ S string }

This way, we’re sure that MyFunc and MyType are defined because they’re referenced by myMap and myMap is referenced from main.

Shameless Plug:

All that being said, I wanted to be able to do something similar to what you’re asking, so I made a package, github.com/skillian/pkgsyms, that generates the necessary code to do this.

You have to execute a command to generate the code:

pkgsyms -package mypkg -output=fmtsyms.go fmt

(You can put it in a //go:generate comment in your program)

Which would generate a file like this:

// Code generated by "pkgsyms -varname fmtPkg -package mypkg -output fmtsyms.go fmt"; DO NOT EDIT.

package mypkg

import (
        "github.com/skillian/pkgsyms"
        "fmt"
)

var fmtPkg = pkgsyms.Of("fmt")

func init() {
        fmtPkg.Add(
                pkgsyms.MakeType("Formatter", (*fmt.Formatter)(nil)),
                pkgsyms.MakeType("GoStringer", (*fmt.GoStringer)(nil)),
                pkgsyms.MakeType("ScanState", (*fmt.ScanState)(nil)),
                pkgsyms.MakeType("Scanner", (*fmt.Scanner)(nil)),
                pkgsyms.MakeType("State", (*fmt.State)(nil)),
                pkgsyms.MakeType("Stringer", (*fmt.Stringer)(nil)),
                pkgsyms.MakeFunc("Errorf", fmt.Errorf),
                pkgsyms.MakeFunc("Fprint", fmt.Fprint),
                pkgsyms.MakeFunc("Fprintf", fmt.Fprintf),
                pkgsyms.MakeFunc("Fprintln", fmt.Fprintln),
                pkgsyms.MakeFunc("Fscan", fmt.Fscan),
                pkgsyms.MakeFunc("Fscanf", fmt.Fscanf),
                pkgsyms.MakeFunc("Fscanln", fmt.Fscanln),
                pkgsyms.MakeFunc("Print", fmt.Print),
                pkgsyms.MakeFunc("Printf", fmt.Printf),
                pkgsyms.MakeFunc("Println", fmt.Println),
                pkgsyms.MakeFunc("Scan", fmt.Scan),
                pkgsyms.MakeFunc("Scanf", fmt.Scanf),
                pkgsyms.MakeFunc("Scanln", fmt.Scanln),
                pkgsyms.MakeFunc("Sprint", fmt.Sprint),
                pkgsyms.MakeFunc("Sprintf", fmt.Sprintf),
                pkgsyms.MakeFunc("Sprintln", fmt.Sprintln),
                pkgsyms.MakeFunc("Sscan", fmt.Sscan),
                pkgsyms.MakeFunc("Sscanf", fmt.Sscanf),
                pkgsyms.MakeFunc("Sscanln", fmt.Sscanln),
        )
}

Then if you wanted to lookup and call fmt.Println from your code, you could do this:

package main

import (
  "log"

  "github.com/skillian/pkgsyms"
)

func main() {
  f, err := pkgsyms.Of("fmt").Lookup("Println")
  if err != nil {
    log.Fatal(err)
  }
  printlnFunc := f.Get().(func(...interface{}) (int, error))
  printlnFunc("Hello, world")
}

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.