Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
go 1.8插件使用自定义界面_Go_Plugins - Fatal编程技术网

go 1.8插件使用自定义界面

go 1.8插件使用自定义界面,go,plugins,Go,Plugins,我想使用基于go插件的自定义界面,但我发现它不受支持 过滤器的定义 此软件包位于我的go应用程序项目中 加载插件文件 这是我的go应用程序项目中加载插件的代码 package main import ( "C" "strings" "time" "github.com/CodisLabs/codis/pkg/utils/log" "github.com/fagongzi/gateway/pkg/filter" "github.com/valya

我想使用基于go插件的自定义界面,但我发现它不受支持

过滤器的定义 此软件包位于我的go应用程序项目中

加载插件文件 这是我的go应用程序项目中加载插件的代码

package main

import (
    "C"
    "strings"
    "time"

    "github.com/CodisLabs/codis/pkg/utils/log"
    "github.com/fagongzi/gateway/pkg/filter"
    "github.com/valyala/fasthttp"
)

// AccessFilter record the http access log
// log format: $remoteip "$method $path" $code "$agent" $svr $cost
type AccessFilter struct {
}

// NewExternalFilter create a External filter
func NewExternalFilter() (filter.Filter, error) {
    return &AccessFilter{}, nil
}

// Name return name of this filter
func (f *AccessFilter) Name() string {
    return "HTTP-ACCESS"
}

// Pre pre process
func (f *AccessFilter) Pre(c filter.Context) (statusCode int, err error) {
    return 200, nil
}

// Post execute after proxy
func (f *AccessFilter) Post(c filter.Context) (statusCode int, err error) {
    cost := (c.GetStartAt() - c.GetEndAt())

    log.Infof("%s %s \"%s\" %d \"%s\" %s %s",
        GetRealClientIP(c.GetOriginRequestCtx()),
        c.GetOriginRequestCtx().Method(),
        c.GetProxyOuterRequest().RequestURI(),
        c.GetProxyResponse().StatusCode(),
        c.GetOriginRequestCtx().UserAgent(),
        c.GetProxyServerAddr(),
        time.Duration(cost))

    return 200, nil
}

// PostErr post error process
func (f *AccessFilter) PostErr(c filter.Context) {

}

// GetRealClientIP get read client ip
func GetRealClientIP(ctx *fasthttp.RequestCtx) string {
    xforward := ctx.Request.Header.Peek("X-Forwarded-For")
    if nil == xforward {
        return strings.SplitN(ctx.RemoteAddr().String(), ":", 2)[0]
    }

    return strings.SplitN(string(xforward), ",", 2)[0]
}
这是插件的定义,在我的插件项目中。插件项目和go app项目是不同的项目

我发现了错误: 您可以在此项目中找到代码https://github.com/fagongzi/gateway/tree/go18-plugin-support.

  • filter.filter
    在pkg/filter包中
  • 在proxy/factory.go中加载插件文件
  • 插件go文件
    位于另一个项目中

  • 自定义接口工作正常

    但有一点很重要:您只能从插件外部定义的插件中查找值(您不能引用插件中定义的类型)。这也适用于“复合类型”的每个组件,例如,您只能类型断言其参数和结果类型也在插件外部定义的函数类型

    1.使用插件外部的通用包 一种解决方案是在插件之外的包中定义接口,插件和应用程序都可以导入并引用它

    在包
    过滤器
    中定义它:

    package filter
    
    type Filter interface {
        Name() string
        Age() int
    }
    
    package main
    
    import (
        "fmt"
        "filter"
    )
    
    type plgFilter struct{}
    
    func (plgFilter) Name() string { return "Bob" }
    func (plgFilter) Age() int     { return 23 }
    
    func GetFilter() (f filter.Filter, err error) {
        f = plgFilter{}
        fmt.Printf("[plugin GetFilter] Returning filter: %T %v\n", f, f)
        return
    }
    
    package main
    
    import (
        "fmt"
        "filter"
        "plugin"
    )
    
    func main() {
        p, err := plugin.Open("pg/pg.so")
        if err != nil {
            panic(err)
        }
    
        GetFilter, err := p.Lookup("GetFilter")
        if err != nil {
            panic(err)
        }
        filter, err := GetFilter.(func() (filter.Filter, error))()
        fmt.Printf("GetFilter result: %T %v %v\n", filter, filter, err)
        fmt.Println("\tName:", filter.Name())
        fmt.Println("\tAge:", filter.Age())
    }
    
    插件位于package
    pq
    中,并导入package
    filter

    package filter
    
    type Filter interface {
        Name() string
        Age() int
    }
    
    package main
    
    import (
        "fmt"
        "filter"
    )
    
    type plgFilter struct{}
    
    func (plgFilter) Name() string { return "Bob" }
    func (plgFilter) Age() int     { return 23 }
    
    func GetFilter() (f filter.Filter, err error) {
        f = plgFilter{}
        fmt.Printf("[plugin GetFilter] Returning filter: %T %v\n", f, f)
        return
    }
    
    package main
    
    import (
        "fmt"
        "filter"
        "plugin"
    )
    
    func main() {
        p, err := plugin.Open("pg/pg.so")
        if err != nil {
            panic(err)
        }
    
        GetFilter, err := p.Lookup("GetFilter")
        if err != nil {
            panic(err)
        }
        filter, err := GetFilter.(func() (filter.Filter, error))()
        fmt.Printf("GetFilter result: %T %v %v\n", filter, filter, err)
        fmt.Println("\tName:", filter.Name())
        fmt.Println("\tAge:", filter.Age())
    }
    
    主应用程序也会导入(相同)包
    过滤器
    ,加载插件,查找
    GetFilter()
    ,调用它,并使用返回的
    过滤器

    package filter
    
    type Filter interface {
        Name() string
        Age() int
    }
    
    package main
    
    import (
        "fmt"
        "filter"
    )
    
    type plgFilter struct{}
    
    func (plgFilter) Name() string { return "Bob" }
    func (plgFilter) Age() int     { return 23 }
    
    func GetFilter() (f filter.Filter, err error) {
        f = plgFilter{}
        fmt.Printf("[plugin GetFilter] Returning filter: %T %v\n", f, f)
        return
    }
    
    package main
    
    import (
        "fmt"
        "filter"
        "plugin"
    )
    
    func main() {
        p, err := plugin.Open("pg/pg.so")
        if err != nil {
            panic(err)
        }
    
        GetFilter, err := p.Lookup("GetFilter")
        if err != nil {
            panic(err)
        }
        filter, err := GetFilter.(func() (filter.Filter, error))()
        fmt.Printf("GetFilter result: %T %v %v\n", filter, filter, err)
        fmt.Println("\tName:", filter.Name())
        fmt.Println("\tAge:", filter.Age())
    }
    
    输出:

    [plugin GetFilter] Returning filter: main.plgFilter {}
    GetFilter result: main.plgFilter {} <nil>
            Name: Bob
            Age: 23
    
    [plugin GetFilterIface] Returning filter: main.plgFilter {}
    GetFilterIface result: main.plgFilter {} <nil>
            Name: Bob
            Age: 23
    
    和主应用程序:

    package main
    
    import (
        "fmt"
        "plugin"
    )
    
    func main() {
        p, err := plugin.Open("pg/pg.so")
        if err != nil {
            panic(err)
        }
    
        GetFilterIface, err := p.Lookup("GetFilterIface")
        if err != nil {
            panic(err)
        }
        filterIface, err := GetFilterIface.(func() (interface{}, error))()
        fmt.Printf("GetFilterIface result: %T %v %v\n", filterIface, filterIface, err)
        myfilter := filterIface.(MyFilter)
        fmt.Println("\tName:", myfilter.Name())
        fmt.Println("\tAge:", myfilter.Age())
    }
    
    type MyFilter interface {
        Name() string
        Age() int
    }
    
    输出:

    [plugin GetFilter] Returning filter: main.plgFilter {}
    GetFilter result: main.plgFilter {} <nil>
            Name: Bob
            Age: 23
    
    [plugin GetFilterIface] Returning filter: main.plgFilter {}
    GetFilterIface result: main.plgFilter {} <nil>
            Name: Bob
            Age: 23
    
    [plugin getFilterFace]返回过滤器:main.plgFilter{}
    GetFilterInterface结果:main.plgFilter{}
    姓名:鲍勃
    年龄:23
    

    另请参见相关问题:

    您使用的是哪种系统?目前Linux上只支持插件。非常感谢您的回答,但这并不能解决问题,因为我描述了不清楚的原因。现在我正在编辑这个问题,事实上我的解决方案与您的解决方案1类似。@ZhangXu我没有看到任何您声称存在的
    过滤器
    包:。你把导入/包路径搞混了。嗨,对不起,它在分支中。我还向golang()打开了一个问题,这可能是一个供应商软件包问题。我将在释放时验证它。插件代码定义在package main中,插件加载在main中。如果插件是从main以外的另一个包加载的,那么这仍然有效吗?换句话说,插件包名是否需要与加载的包名匹配(在您给出的示例中为main)?@chmike插件必须具有package
    main
    ,并且可以从任何地方加载。但是一个可运行的应用程序还必须有一个包
    main
    ,包
    main
    main()
    函数是该应用程序的入口点。插件的
    main
    和应用的
    main
    是两个不同的包。