诺禾-诺禾手把手教你用Golang封装一款适合自己使用的Web编程框架

非正式解决方案
思考链接价值,非正式解决方案,既扯高大上如人工智能、大数据,也关注码农日常如分布式、java和golang,每天分享瞎想的东西。
MVC 应用一般结构
目录结构说明如下
名称内容model模型层目录,类比Java 中的entityview视图层,存放所有templete模板ctrl控制器层, 存放全部控制器service服务层,类比Java里面的servicehtml一些静态资源页面util核心工具包,Md5加密,返回数据封装等asset静态资源目录,存放js/css/image等args封装全部请求参数对象mnt上传文件的存放目录app.dev.conf开发环境配置文件app.prod.conf生产环境配置文件start.sh/start.bat启动脚本build.sh/build.bat打包脚本main.go主应用程序文件
主程序结构
主程序主要做各种初始化工作
func main() { //解析配置文件 fpath := flag.String(“c”,“app.dev.conf”,“config file path”) flag.Parse() _,err:=util.Parse(fpath) if err!=nil{ fmt.Sprintf(“error when %s”,err.Error()) return } //配置日志 logmap := util.GetSec(“log”) service.InitLog(logmap) //初始化数据库 dbmap := util.GetSec(“database”) service.InitDb(dbmap) //注册funcmap ctrl.RegisterFuncMap() //控制器 ctrl.RegisterCtrl() //静态资源文件 fileservermap := util.GetSec(“fileserver”) ctrl.InitFileServer(fileservermap) //初始化session sessioncfg:=util.GetSec(“session”) util.StartSession(sessioncfg) appcfg := util.GetSec(“app”) //视图控制器 ctrl.RegisterView(appcfg) fmt.Println(“http ListenAndServe " + appcfg[“addr”]) //打开服务器监听http err = http.ListenAndServe(appcfg[“addr”], nil) if err!=nil{ fmt.Println(err.Error()) log.Println(err.Error()) }}配置文件
3.1 配置文件解析
使用配置文件开发包,如github.com/Unknwon/goconfig 包。
//util/config.govar cfg goconfig.ConfigFilevar cfgmap map[string]map[string]string = make(map[string]map[string]string)var filepath string//解析peizfunc Parse(fpath string)(c map[string]map[string]string ,err error){ cfg, err := goconfig.LoadConfigFile(fpath) filepath = fpath sec :=cfg.GetSectionList() for _,v :=range sec{ cfgmap[v]=make(map[string]string,0) keys := cfg.GetKeyList(v) for ,b:= range keys{ cfgmap[v][b], = cfg.GetValue(v,b) } } return cfgmap,err}//全部都存放在存放func GetAllCfg()(c map[string]map[string]string){ return cfgmap}//重新刷新配置文件func ReloadAllCfg()(c map[string]map[string]string){ return return Parse(filepath)}调用案列
util.GetAllCfg()[“app”][“port”]3.2 监听配置文件并自动刷新配置
使用github.com/fsnotify/fsnotify包,装时候注意,一个函数里面如果有参数共享,应该放到一个携程里。
//监听文件func WatchConfig(filepath …string) { //创建一个监控对象 go func() { watch, err := fsnotify.NewWatcher() if err != nil { log.Fatal(err) } defer watch.Close() //添加要监控的对象,文件或文件夹 for _, fpath := range filepath { err = watch.Add(fpath) if err != nil { log.Fatal(err) } fmt.Println("WatchConfig " + fpath) } for { select { case ev := <-watch.Events: { if ev.Op&fsnotify.Write == fsnotify.Write { //监听到文件系统使用加载新东西 ReloadAllCfg() } fmt.Println(ev.Op, ev.Name) } case err := <-watch.Errors: { log.Println("error : ", err) return } } } }()}fsnotify 支持很多种事件监听,一般在 Write 事件刷新配置文件
//判断事件发生的类型,如下5种// Create 创建// Write 写入// Remove 删除// Rename 重命名// Chmod 修改权限if ev.Op&fsnotify.Create == fsnotify.Create { log.Println("创建文件 : ", ev.Name);}if ev.Op&fsnotify.Write == fsnotify.Write { log.Println("写入文件 : ", ev.Name);}if ev.Op&fsnotify.Remove == fsnotify.Remove { log.Println("删除文件 : ", ev.Name);}if ev.Op&fsnotify.Rename == fsnotify.Rename { log.Println("重命名文件 : ", ev.Name);}if ev.Op&fsnotify.Chmod == fsnotify.Chmod { log.Println("修改权限 : ", ev.Name);}3.3 区分系统级配置和用户级配置
系统级配置参数 假设修改了会影响整个应用,需要另起服务的我们称之为系统级配置,修改了参数,往需要进行相应的操作。如修改了数据库连接地址,需要重置数据库连接操作。修改了应用服务器端口,则需要重启应用服务。
用户级配置参数 如微信公众号 appsecret,每次调用的时候会从配置中获取,因此只需要重新加载数据即可。
3.4 配置内容缓存
需要将配置文件内容缓存到 map 中。 需要考虑到 map 的并发操作。
实体层(model)写法
4.1 状态变量定义在实体文件内部
//model/user.go//用户性别和角色const ( WOMEN=2 MAN=1 Unknow=0 ROLE_ADMIN =1 ROLE_USER=0)type User struct {Id int64 xorm:"pk autoincr BIGINT(20)" form:"id" json:"id"NickName string xorm:"VARCHAR(40)" form:"nickName" json:"nickName"Openid string xorm:"VARCHAR(40)" form:"openid" json:"openid"M

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值