说明
本插件是教大家如何开发框架utils->plugin下扩展插件包,在开发时可安装本插件,参考本插件代码结构写你插件,这样可以达到规范插件代码,同时也也是为了兼容你安装其他人在代码仓通过扩展插件包,如果不规范可能发生在utils->plugin包下函数命名冲突,代码规范也是方便在app业务代码中调用和代码维护。
扩展插件开发规范
这里我们用demo名称作为演示教程扩展插件包名称,下面都以demo名称讲,在你实际开发你的扩展插件包是替换成你取包名,下面将按照开流程讲述开发过程。
1.扩展插件包取名
名称建议用英文字母,结果可以使用驼峰名称法。取好名称后在你使用前,先到后端的开发者工具->代码仓的右上角的“检测包名”,输入你取的包名,检测通过在点“立即占用”来占用你取的包名,如下图:
2.创建扩展包文件及目录
在utils->plugin目录下创建一个xx.go文件和xx文件夹,切记这文件和文件夹命名必须一样,否则打包选择xx.go时不能把它对应的xx文件夹一同打包到zip压缩包里,其中xx是你要开发扩展包名称,例如我们当前演示名称为demo
目录机构如下:
├─ utils # 框架核心代码及工具包
│ ├─ plugin # 框架扩展目录
│ │ ├─ demo # 扩展插件功能文件目录
│ │ │ ├─ example.go # 插件功能函数
│ │ │ └─ util.go # 通用工具函数
│ │ └─ demo.go # 扩展插件入口文件(主文件)
3.util.go文件
util.go是给demo目录下插件功能函数公共调用函数,比如统一或插件配置文件内容,公用处理某个功能函数等,本例演示的demo是读取配置文件并配件请求地址,代码如下:
// ---
// @title 通用工具函数
// @des util就是用于编写插件公用的工具函数,如果没有公用函数就不用创建util.go
// 下面给的GetUrl和RequestHttp两个是为了演示用的,在开发是大家更加业务自己编写
package demoimport ("fmt""gofly/utils/gf""gofly/utils/tools/gconv"
)// 这获取resource/config下名称和plugin扩展插件名字一样配置文件,本例就是获取demo.yaml配置数据
var (cosdata, _ = gf.GetConfByFile("demo")CosConf = gconv.Map(gconv.Map(cosdata)["data"])
)// 获取完整请求地址
func GetUrl(path string) string {return fmt.Sprintf("%v%v", CosConf["url"], path)
}
4.插件的功能函数(example.go)
这是编写具体功能函数文件,每个文件编写同一类型功能(这个经典例子可以安用Zinc全文搜索引擎这个插件就按照Index.go索引,Doc.go文档分类)。演示插件是在example.go中写业务代码,文件创建一个名称和文件名一样的结构体,但是名字首字母必须是大写,如:Example 还有把(api *Example)结构添加到函数前面,这样我们在调用时就可以链式操作了。演示代码中的GetData和GetList是功能函数,它就是处理指定的功能。好有后面的Page和FindTitle是给结构体内变量赋值,在调用功能函数(GetData和GetList)前调用Page和FindTitle类设置PageNum、PageSize、Title的值。
代码如下:
// ---
// @title 实现功能
// @des 这里是实现具体功能,我们某一分类的功能放在一起,如果多个类型功能我们就创建多个文件。
// 这里的example.go是给大家演示功能用的,所以我们取名example,在开发中更加实际业务取名。
package demoimport ("fmt"
)
// 插件功能类名称
type Example struct {PageNum int //页数PageSize int //条数Title string //通过标题进行模糊查询
}// 测试获取单条数据
// 参数:devcode=传给接口数据
func (api *Example) GetData(devcode interface{}) (res string, err error) {weburl := GetUrl(fmt.Sprintf("/business/cronjob/getTest?dev_code=%v", devcode))res, err = RequestHttp("GET", weburl, "")return
}// 测试获取列表数据
func (api *Example) GetList() (res string, err error) {weburl := GetUrl(fmt.Sprintf("/business/createcode/product/getList?page=%v&pageSize=%v&title=%v", api.PageNum, api.PageSize, api.Title))res, err = RequestHttp("GET", weburl, "")return
}// -------------------------这里写接口的属性链式操作--------------------------
// 设置分页数据
func (api *Example) Page(page, pagesize int) *Example {api.PageNum = pageapi.PageSize = pagesizereturn api
}// 设置查询的标题内容
func (api *Example) FindTitle(title string) *Example {api.Title = titlereturn api
}
5.扩展插件入口文件(主文件)
这里是让app下业务代码可以用plugin去调用插件函数,在这里我们把插件做统一调用实例化,这样在使用时可以直接通过扩展插件名去调用函数。如果你的插件功能简单代码不复杂则可以直接在这个文件写完,不需要再创建一个同名称的文件夹来写写具体功能函数。在下面的演示代码我们看到NewDemo是给插件统一实例化入口函数,func (*Demo) Example() *demo.Example{}是把插件对应目录下功能类文件关联到Demo插件下,这样可以用Demo.Example调用具体函数了,并且在实例Example同时可给他结构体内变量的默认值。
演示插件代码如下:
// ---
// @title Demo扩展插件的入口文件
// @des
package pluginimport ("gofly/utils/plugin/demo"
)// 创建插件结构-要求与文件名一致,首字母必须大写,不然app下的应用无法调用
type Demo struct{}// Demo接口实例
func NewDemo() *Demo {return &Demo{}
}// 把demo下的功能函数example
func (*Demo) Example() *demo.Example {return &demo.Example{PageNum: 1, PageSize: 10}
}
到这里我们扩展插件就开发好了,下面我们在讲如何在app下的业务代码中调用扩展插件。
在app的业务代码中调用示例
我们测试模块app/business/createcode中创建一个demo.go文件来测试调用扩展插件接口,测试代码中我们先import导入"gofly/utils/plugin"扩展包,然后用plugin.扩展插件实例函数.功能文件名.功能函数,即:pluginplugin.NewDemo().Example().GetData(),之间还根据需求添加属性设置函数如Page(1, 10)设置分页数据,这样我们就可以格式清晰的使用扩展插件功能了。
测试调用代码如下:
package createcodeimport ("gofly/utils/gf""gofly/utils/plugin"
)// 测试demo演示插件接口
type Demo struct{}func init() {fpath := Demo{}gf.Register(&fpath, fpath)
}// 测试获取单条数据
func (api *Demo) GetData(c *gf.GinCtx) {param, _ := gf.RequestParam(c)res, err := plugin.NewDemo().Example().GetData(param["title"])if err != nil {gf.Failed().SetMsg("测试获取单条数据失败").SetData(err).Regin(c)return}gf.Success().SetMsg("测试获取单条数据成功").SetData(res).Regin(c)
}// 测试获取数据列表
func (api *Demo) GetList(c *gf.GinCtx) {param, _ := gf.RequestParam(c)res, err := plugin.NewDemo().Example().Page(1, 10).FindTitle(gf.String(param["title"])).GetList()if err != nil {gf.Failed().SetMsg("测试获取数据列表失败").SetData(err).Regin(c)return}gf.Success().SetMsg("测试获取数据列表成功").SetData(res).Regin(c)
}