配置文件(类似于spring 加载 *.properties文件)
https://studygolang.com/articles/5160
通过 goconfig 的第三方类库实现
- 支持相对路径和绝对路径的两种加载方式
- 都是加载到内存当中的,值以第一次加载的为准,不会自动热加载,但是可以通过cfg.Reload()进行重新加载
- config文件分为两部分 SECTION 和key
- 键值对支持两种配置形式: name = huangzs ; name : huangzs
# 配置
[db]
dsn = root:123456@tcp(127.0.0.1:3306)/goNovel?charset=utf8
[common]
downloadUrl = http://www.booktxt.net/2_2219/
# Go引用
//相对路径
cfg, err := goconfig.LoadConfigFile("config/conf.ini")
//绝对路径
cfg, err := goconfig.LoadConfigFile("C:/huangzs/workspaceGo/src/webProject/config/conf.ini")
//获取默认分区的key为key_default的值
value, err = cfg.GetValue("", "key_default")
//重新加载配置文件
err = cfg.Reload()
Go原生路由的使用
chainzhang博客
https://www.jianshu.com/p/ae9b5628d18b
- 自定义一个路由器,实现业务的Handler映射规则
type MyMux struct{
}
func (p *MyMux)ServeHTTP(w http.ResponseWriter, r *http.Request){
if r.URL.Path == "/"{
index(w, r)
return
}
if r.URL.Path == "/download"{
novel.DownloadNovle()
return
}
if r.URL.Path == "/read"{
readNovel(w, r)
return
}
http.NotFound(w,r)
return
}
- 把路由器作为参数,传到ListenAndServe当中
func Start(){
mux := &MyMux{}
err := http.ListenAndServe(":9090", mux)
if err != nil{
log.Fatal("ListenAndServe: ", err)
}
}
- Main方法启动的时候,调用 Start()
模板引擎
https://www.jianshu.com/p/05671bab2357
- 默认模板引擎的渲染是即时的,默认加载最新的静态文件,有点像JSP
- Beego的模板是预加载的,提升了渲染速度,适合生产环境,但是开发环境,每次改了静态文件要重启
- 原生的模板语法,支持类似于JSP的 if判断等等语法,模板之间include、range遍历等等
数据的传递
- 通过往template.Execute往模板中直接写数据,然后模板文件中可以获取
func index(w http.ResponseWriter, r *http.Request){
r.ParseForm() //解析form
t, _ := template.ParseFiles("./templates/index.html")
t.Execute(w, "hello kitty")
}
<body>
<h3>This is layout</h3>
template data: {{ . }}
</body>
- 往template里面直接传一个对象,然后取对象的属性
func index(w http.ResponseWriter, r *http.Request){
r.ParseForm() //解析form
t, _ := template.ParseFiles("./templates/index.html")
user :=&User{Name:"huangzs",Age:20,Sex:"male"}
t.Execute(w, user)
}
<body>
<h3>This is layout</h3>
template data:
<p> name :{{.Name}};</p>
<p> age: {{.Age}};</p>
<p> sex: {{.Sex}} </p>
</body>
- 往template里面传一个数组,然后遍历数组的值
func index(w http.ResponseWriter, r *http.Request){
r.ParseForm() //解析form
t, _ := template.ParseFiles("./templates/index.html")
user1 :=&User{Name:"huangzs1",Age:20,Sex:"male"}
user2 :=&User{Name:"huangzs2",Age:30,Sex:"male"}
user3 :=&User{Name:"huangzs3",Age:40,Sex:"male"}
users := []User{*user1,*user2,*user3}
t.Execute(w, users)
}
{{ range . }}
<div>
<li>Name: {{ .Name }}</li>
<li>Age: {{ .Age }}</li>
<li>Sex: {{ .Sex }}</li>
</div>
{{ end }}
- 后台接收参数的时候一定要注意,默认是把参数的值当成一个数组的,即使你传的只有一个值
比如 /read?id=1 ,获取id参数的时候,会把id这个值当成数组,所以取第一个,才是正确的
t, _ := template.ParseFiles("./templates/novel.html")
idnum,err:=strconv.Atoi(r.Form["id"][0])
- 传输的数据,默认是忽略 html语法的,如果想在内容中插入原生的html标签的话,
- 一种解决方案是使用Beego的str2html函数
- 一种解决方案是把html内容写死,直接返回html
<div >
{{.chapter.Content | str2html}}
</div>
- 支持字符串的非空校验
- 正则表达式匹配
- 数字大小判断等等
if len(r.Form["username"][0])==0{
fmt.Fprintf(w, "username: null or empty \n")
}
age, err := strconv.Atoi(r.Form.Get("age"))
if err != nil{
fmt.Fprintf(w, "age: The format of the input is not correct \n")
}
if age < 18{
fmt.Fprintf(w, "age: Minors are not registered \n")
}
if m, _ := regexp.MatchString(`^([\w\.\_]{2,10})@(\w{1,}).([a-z]{2,4})$`,
r.Form.Get("email")); !m {
fmt.Fprintf(w, "email: The format of the input is not correct \n")
}