Golang中国
//根据json
{"name":"年龄","opera":"==","value":25},
{"name":"性别","opera":"==","value":"男性"}
//生成代码
func GetResult(data map[string]interface{})string{
    if data["年龄"]==25&&data["性别"]=="男性" {
        return "小明"
    }
}

// 前端传递过来的json
data:=map[string]interface{}{
    "年龄":25,
    "性别":"男性",
}

//在api里动态调用生成的代码
func GetOne(data map[string]interface{})(string,error){
    return GetResult(data),nil
}

1.使用第三方otto包可以嵌入js代码,不支持动态加载

//生成
package test

import (
    "github.com/robertkrimen/otto"
)

type client struct {
    VM *otto.Otto
}

func NewOtto() *client {
    return &client{VM: otto.New()}
}
func (c *client) Run() string {
    c.VM.Run(`
        if (年龄==25&&性别=="男性"){
            result="小明"
        }
    `)
    v, err := c.VM.Get("result")
    if err != nil {
        panic(err)
    }
    value, err := v.ToString()
    if err != nil {
        panic(err)
    }
    return value
}

//调用
import (
    "test"
    )
func GetOne(data map[string]interface{})(string,error){
    js := test.NewOtto()
    for k, v := range data {
        js.VM.Set(k, v)
    }
    return js.Run(), nil
}

2.使用伪包C可以嵌入c代码

// 生成

// foo.h
char* getResult(int,char*);

// foo.c
#include "foo.h"

char* getResult(int age,char* sex) {
    if (age==25&&sex=="男性"){
        return "小明";
    }
}

// 编译
$> gcc -c foo.c
$> ar rv libfoo.a foo.o
//调用

package main
// #cgo LDFLAGS: -L ./ -lfoo
// #include <stdio.h>
// #include <stdlib.h>
// #include "foo.h"
import "C"

func main() {
    sex:=C.CString("男性")
    result:=C.GoString(C.getResult(25,sex))//小明
}

3.格式化后编译成包,不支持动态加载

// 生成
package test
type business struct{
   data map[string]interface{}
}
func NewData(value map[string]interface{})*business{
    return &business{data:value}
}
func (b *business) GetResult()string{
  if b.data["年龄"]==25&&b.data["性别"]=="男性"{
   return "小明"
  }
}
// 编译
import "os/exec"
exec.Command("gofmt")
exec.Command("go", "build",filePath)

// 调用
import (
    "test"
    "reflect"
    "errors"
    )
func GetOne(data map[string]interface{})(string,error){
    obj:=reflect.ValueOf(test.NewData(data))
    fun:=obj.MethodByName("GetResult")
    if !fun.IsValid(){
        return "",errors.New("GetResult不存在")
    }
    return fun.Call(nil)[0].String(),nil
}

还有没有其他动态调用方法?


fanyang 于 2016-12-15 11:01 修改
6 回复
joe9i0
#1 joe9i0 • 2016-12-03 13:08

Go1.8 加入插件机制
https://beta.golang.org/pkg/plugin/

fanyang
#2 fanyang • 2016-12-03 14:19

可惜1.8还在测试

// hello.go
package main

import "fmt"

func Hello(name string)string{
return fmt.Sprintf("Hello,%s",name)
}

$ go build -buildmode=c-shared hello.so hello.go

// main.go
package main

import (
   "plugin"
   "fmt"
  )

func main() {
 p, _ = plugin.Open("hello.so")
 f := p.Lookup("Hello")
 fmt.Println(f.(func(string)string)("golang"))
// Hello,golang
}
joe9i0
#3 joe9i0 • 2016-12-04 14:03

还在测试没关系, 官方列出这个特性在1.8发布, 这期间可以开发自己的业务, 再等两个多月1.8正式版本发布了, 升级一下SDK就可以了.

fanyang
#4 fanyang • 2016-12-08 11:49

好的,不过我这两天还测试了个方案,生成api

zmguozi
#5 zmguozi • 2016-12-08 12:13

七牛开源了一个qlang,专门做这事.

fanyang
#6 fanyang • 2016-12-08 14:35

看样子比lua还要好点,我得一个个测试下性能

需要 登录 后方可回复, 如果你还没有账号你可以 注册 一个帐号。