Need help for Golang how to call a package function/s by string name from another package and send the struct data to it

2,175 views
Skip to first unread message

pgb...@gmail.com

unread,
Jul 6, 2015, 12:33:10 PM7/6/15
to golan...@googlegroups.com
Hello all :),
I`m new in Golang and have a problem with calling a package function/s by string name from another package.
i read a lot of this topic and still can`t find a solution for my problem :(
This is the first time i write anything on the web forums ever so please excuse me for the noob writing.
I will try to give you as much info as possible for my problem so ..

I'm trying to build web base small framework with dynamic struct of data looking like this :

1.Framework core functions location is : ../src/core/myStruct
package myStruct {

  type MFunc map[string]func();
  type MapStr map[string]string;
  ....

  type TableRec struct {
      TABLE_OPTIONS  TableData;  // table options from JSON file
      FIELDS MapData;            // fields from JSON file
      .....
      METHODS   MapStr;
     // METHODS   MFunc; // MFunc get a error :`(  =>( EXTRA *json.SyntaxError=invalid character 'F' looking for beginning of value)
  }

}

2.load JSON from System1 location : ../src/sys/System1/tables
Json file ..:
{
        "TABLE_OPTIONS" : {
          "TABLE_NAME": "FORM_INS",
          "SYSTEM_ON" : "System1",
            ...........
    },
    "METHODS" : {
        //"on_insert" : Form_ins_insert // error from MFunc

        "on_insert"   : "Form_ins_insert"  //MapStr work :/ 
          ......
    }, 
    "FIELDS" : {
        "ID" : {
            "TYPE"   : "INT",
            "VALUE"  : 0,
            "OPTIONS": { "RO": 1 , "HID": 0 }
        },
        "NAME" : {
                "SEP": { "en" : "Person Data" , "bg" : "Данни за клинета" },
            "LABEL":  {  "en" : "Full name","bg" : "Пълно име"  },
            "TYPE": "CHAR",
            "VALUE": "",
            "SIZE" : 200,
            "OPTIONS": {"ROW": 2 , "ROW_SIZE": 100  }
        },
        ......
    }
    .....
}


3  Must call func from System1 (or System2, or System3 ...) and send it the struct with the data i push in the struct in the core

 location : ../src/sys/System1/methods

package methods

import (
    "fmt"
    _ "../core/myStruct"   
)

func Form_ins_insert(rec *TableRec) (html string) {
  fmt.Println("================== Form_ins_insert ================");
  fmt.Println("\t\t on table =",rec.TABLE_OPTIONS.TABLE_NAME);
 
  // i must get to this point but have 0 ideas how :`( .....

 
  return html;
}


4 !!!! THE PROBLEM PART !!!!!

And the "callerFunc" (the relay station) calling System1,..,SystemN

location : ../src/sys

package sys

import (
    "fmt"
     "../core/myStruct"
     _ "../sys/System1/methods"
     _ "../sys/System2/methods"  // i thing i must set all systems here 1 by one ...
)

func CallSysMeth(rec *myStruct.TableRec, name string) {
    myRec := rec;
     
    fmt.Println("================== CallSysMeth ================");
    fmt.Println("======method name to call =",name," , Struct=",myRec.METHODS);

    // THIS PART IS LOST IN TRANSLATION FOR ME ?!?!?!?!?!?!?!?!?!?!?!?!
    // how to call system1 from "rec.TABLE_OPTIONS.SYSTEM_ON" with method name "Form_ins_insert" and send it the struct ????

    ......
}


I`m open for any ideas what ever how to make it work but how to make it better.
Keep in mind that every "table" can have a different methods and any "system" can have this methods and tables so i must call system from the "rec.TABLE_OPTIONS.SYSTEM_ON" with the method from "METHODS" list.
I decide to make it in JSON objects for flexibility so small changes like changing the labels (translating ) ор OPTIONS can be made without server restarts compiles and so on.




Konstantin Khomoutov

unread,
Jul 6, 2015, 1:19:43 PM7/6/15
to pgb...@gmail.com, golan...@googlegroups.com
On Mon, 6 Jul 2015 01:31:34 -0700 (PDT)
pgb...@gmail.com wrote:

> I`m new in Golang and have a problem with calling a package
> function/s by string name from another package.

You can't. At least, you can't directly. That is, is your package "B"
imports package "A" which exports function "Foo", there's no way to
call B's "Foo" given a *string* constant/value containing that name.

There's several thing you can do about this:

1) Do not attempt to call anything by name.
You supposedly came from PHP or some other dynamic language
and are trying to apply your learned skills here.
This is understandable but usually wrong.

2) What you want to do is called mapping: you want to map a string
containing certain value to a function.

But Go already has maps for you.

Supposed that B.Foo has signature

func (i int) (string, error)

Then just go ahead and prepare a map:

var funcs = map[string](int) (string, error) {
"Foo": B.Foo,
}

and then you'll be able to call

funcs["Foo"](42)

(Playground link: http://play.golang.org/p/NuleqshVdm).

[...]

Blagoy Petrov

unread,
Jul 7, 2015, 2:53:47 AM7/7/15
to golan...@googlegroups.com, pgb...@gmail.com
Thanks for the answer :)
I`m writing in GO for 9 days till now so pretty much i'm a noob  in it :)
And yes i'm coming from dynamic lang. but it's not PHP please ...
It`s Perl and it`s not wrong to try doing something different or in a different way.
This is what programmers do :P , lamers go only for the thing they see somewhere with 0 perspective and knowing how the thing work or can work...

I need dynamic way to do this map...
I can't afford server down time but can afford to have a sec. delay.
JSON struct of the objects is ONLY internal not gonna take them from outside world so it`s SAVE and don`t need restart if you change something inside and the system just will start working with the new things :)
Need something similar and dynamic for this "map".

I see alot of this "map" on the web but in this case is not working at all.
This however is similar to your solution and work for the case i write above and give all struct of the data but also need restart :(

package sys
.....
var (        
  callSYS = map[string]p_types.MFunc{
        "System1": {
                "Form_ins_insert"   : func (rec *p_types.TableRec) { methods.Form_ins_insert(rec); },
                .......
        } ,
        ...
    }

 )

func CallSysMeth(rec *p_types.TableRec, meth string) {
     sys := getStr(rec.Sess.Base);     
    
     if _, haveIt := callSYS[sys][meth]; haveIt == true {
        callSYS[sys][meth](rec);   
     } else {
        fmt.Println("SYS ERROR:  UNDEFINED METHOD ",meth," OR SYS : ",sys);
     }
}


So again need dynamic way to do this map...
Like... loading from a file or something like it.
I can load packages and funcs on runtime in Perl don`t realy thing can do it in GO :/
For now i'm doing it just from sports malice.
I NEED TO KNOW what i can do and can`t do with every lang. i decide to write on.
And for now Perl rule on functionality.
Go it`s faster probably i can remove the apache and nginx and use Go code for the web server it will gonna speed my code alot ...
But need to write all in GO first to compare every pluses and minuses of writing dynamic systems on it.

Don't get me wrong i can write on  Assembler, C, VC, JAVA, C# , Cocoa, Perl and now GO :) i`m just crazy and really like to write a code
Also work daily with DBs for (8+ years) like postgres and Oracle ( my favorite).
I think GO is worth trying, still have a lot of bugs (mostly in the struct-s) but it`s nice and hope they will fix it some day :D

Egon

unread,
Jul 7, 2015, 3:54:34 AM7/7/15
to golan...@googlegroups.com


On Monday, 6 July 2015 19:33:10 UTC+3, Blagoy Petrov wrote:
Hello all :),
I`m new in Golang and have a problem with calling a package function/s by string name from another package.
i read a lot of this topic and still can`t find a solution for my problem :(
This is the first time i write anything on the web forums ever so please excuse me for the noob writing.
I will try to give you as much info as possible for my problem so ..

Yup, that's a good way to ask questions :)

First check out the naming guidelines


Following those guidelines makes all packages/libraries consistent in style - meaning you can pretty easily drop into any package and start reading it. PS. go lint helps to find some of those. 
 

I'm trying to build web base small framework with dynamic struct of data looking like this :

1.Framework core functions location is : ../src/core/myStruct

Try to name things more meaningful - it helps to guide the design process, e.g i would name the package "table"... that way I can have type "Record' this will eventually look in elsewhere

table.Record
table.Method
table.Methods
table.Fields

It keeps the usage elsewhere really clean.
 
package myStruct {

Remove the "{", it's not necessary.

Anyways finally to the actual problem.


Although, if you are working with dynamic and easily modifiable rules then you might consider embedding lua (or some other dynamic language) as the event handling.

Regarding server down time, you can do a graceful restart.

I.e. bring up a new server, direct users to the new server, once all the users are using the new server shutdown the old server. Usually putting it behind a load-balancer is a quick way to do it (https://www.reddit.com/r/golang/comments/36sit8/how_do_you_update_a_production_server/).

+ Egon

Tamás Gulácsi

unread,
Jul 7, 2015, 4:21:44 AM7/7/15
to golan...@googlegroups.com
For dynamic plugins, try https://github.com/natefinch/pie - all plugin is a separate executable, started by the main program, communicating through stdin/stdout.
Reply all
Reply to author
Forward
0 new messages