楔子
最近因为996的事情分散了很多的精力,做了一个游戏的策划,但是毕竟不是专业做游戏的,同时也没有人加入协助,我很可能把它给鸽掉。不过呢,由此了解了一个galgame的牛叉游戏引擎renpy,使用python写的,所以除了做单纯的galgame以外,还可以使用原生python做其他的游戏,等有时间研究了倒是可以单独写一篇文章介绍一把。
做一个系统,其中有一个功能是系统管理,系统管理的的设置可以选择直接保存在数据库,也可以写一个统一的配置文件(text、json、yaml各种)再把这个文件保存在数据库,当然还有一种方式是直接写一个配置文件扔在本地,就像beego的app.conf一样。
在ilus里面,我选择使用yaml文件,好处嘛,比json更为精简,又比传统配置文件多了对应关系,方便你随时读取和对目标值进行修改。
今天就谈一谈如何读写yaml并写一个后台页面进行修改
ilus里面对yaml的读写操作并没有使用beego自带的工具,而是使用了一款应用比较广的Golang Yaml工具库,go-yaml
go-yaml
这是我感觉使用起来比较方便的工具类,目前的版本为v2.2.2
直接安装
go get gopkg.in/yaml.v2
读取
写在读取之前,需要谈一下,因为这次的功能是系统设置,为了方便调用,我把所有的设置像app.conf的内容一样,在系统加载的时候进行了预制,位置就在BaseController的Prepare方法里面,所有信息在启动的时候就放到了内存里面,这样做的好处就是不需要在每次调用的时候再去频繁读本地文件。
func (c *BaseController) Prepare() {
//附值
c.controllerName, c.actionName = c.GetControllerAndAction()
//从Session里获取数据 设置用户信息
c.adapterUserInfo()
//从app.conf里面读取系统信息
c.setAppInfo()
//从sysInfo.yml里面读取系统设置信息
c.getSystemInfo()
}
上面的代码是BaseController里面的调用
//getSystemInfo 初始化系统设置
func (s *SystemSettings) getSystemInfo() {
//从本地文件读取yaml流
yamlFile, err := ioutil.ReadFile("./conf/sysInfo.yml")
if err != nil {
fmt.Println(err)
}
//解析yaml文件,并注入到SystemSettings的结构体里面
err = yaml.Unmarshal(yamlFile, s)
if err != nil {
fmt.Println(err.Error())
}
}
上面的代码就是从yaml文件里面读取文件流,然后解析,并注入结构体。结构体写的很丑,就不好意放出来了,有需要的朋友直接去源码里面看吧。老实说整个系统设置的代码我感觉写的都很丑,有些仓促,回头有时间再做优化。
保存
保存其实很简单,不过需要注意的是,如果我们是从html里面直接post提交,那么我们提交的类型都是统一的string,面对golang这么严谨的代码风格,非string类型的字段都需要进行转化,比如结构体的某个字段:Indexnum int
定义为整形,那么读取之后就必须进行转化后再赋值
//把string类型改为int类型
i, _ := strconv.Atoi(c.Ctx.Request.PostForm.Get("index_posts"))
//变更结构体里面的值
c.SystemSettings.Indexnum = i
这里你就能看到了,保存其实是分两部分的,首先你需要把结构体的对应字段进行修改,也就是先改内存的值,然后再改文件的值,只保存到结构体里面,重启就覆盖了,只保存到文件里面那么就必须重启才能生效。
//把结构体直接序列化
d, err := yaml.Marshal(c.SystemSettings)
//把序列化的内容写入文件
ioutil.WriteFile("./conf/sysInfo.yml", d, os.ModeAppend)
写入文件的方法中第三个参数代表如果文件存在,则将文件全部清空然后重新写入,这样写比较方便,即便只修改一个值。
beego模版引擎
前段用到了一个beego的模版引用,主要是为了实现多个标签页。其实直接写在一个html文件里面也没有问题,但是为了「程序员的执着」因此还是用到了模版引用。
head和foot部分的引用直接看源码就可以了,这里说一下tab:
<!-- Main content -->
<section class="content container-fluid">
<!-- 页面内容开始 -->
<div class="row">
<div class="col-md-12">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
<li class="active"><a href="#general" data-toggle="tab">常规设置</a></li>
<li><a href="#seo" data-toggle="tab">SEO设置</a></li>
<li><a href="#article" data-toggle="tab">文章设置</a></li>
<li><a href="#comment" data-toggle="tab">评论设置</a></li>
<li><a href="#attach" data-toggle="tab">附件设置</a></li>
<li><a href="#admin" data-toggle="tab">后台设置</a></li>
<li><a href="#email" data-toggle="tab">邮箱设置</a></li>
<li><a href="#other" data-toggle="tab">其他设置</a></li>
<li class="pull-right"><a href="#" class="text-muted"><i class="fa fa-gear"></i></a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="general">
{{template "system/general.html" .}}
</div>
<div class="tab-pane" id="seo">
{{template "system/seo.html" .}}
</div>
<div class="tab-pane" id="article">
{{template "system/article.html" .}}
</div>
<div class="tab-pane" id="comment">
{{template "system/comment.html" .}}
</div>
<div class="tab-pane" id="attach">
{{template "system/attach.html" .}}
</div>
<div class="tab-pane" id="admin">
{{template "system/admin.html" .}}
</div>
<div class="tab-pane" id="email">
{{template "system/email.html" .}}
</div>
<div class="tab-pane" id="other">
{{template "system/other.html" .}}
</div>
</div>
</div>
</div>
</div>
</section>
上面代码分为两部分,一部分是定义每个tab的名称并声明href地址,另外一个就是模版引用,在beego里面使用双大括号 template关键字 空格 加上模版地址构成{{template "system/attach.html" .}}
注意:注意后面的空格+ .
,这个可不是随便写的,在beego里面后面的点代表把当前页面的信息传递到子页面里面,如果不加这个点的话,在子页面就不可以直接使用模版引擎函数来直接呈现后台数据了。
接下来因为工作原因我有可能会写一些会员管理的相关功能,当然也有可能不写….嗯….人生就是很纠结...
有疑问加站长微信联系(非本文作者)