==============================================beego框架===========================================html
1.使用beego框架上传文件前端
问题描述:文件上传失败,出现The filename, directory name, or volume label syntax is incorrectweb
问题分析:在上传文件时,为了不文件名重复带来的文件覆盖问题,使用时间对文件进行重命名。时间格式:YYYY-MM-DD HH:mm:ss。当文件路径中出现冒号是,会出现上述错误。算法
解决方法:去掉文件中的冒号,文件名改用YYYY-MM-DD-HH-mm-ss格式,问题解决后端
2.beegoweb开发页面日期显示格式问题数组
问题描述:在web开发时,常常会从后台读取数据到前端显示,可是有时候日期的格式并不是咱们想要的格式安全
解决方法:beego提供了日期显示时的格式化方法:cookie
{{.Atime.Format "2006-01-02 15:04:05"}}
3.后端获取的列表在前端页面显示的方法session
问题描述:web开发时,常常须要从后台查询获取数据列表,那么数据列表在表单如何遍历显示呢数据结构
解决方法:beego提供了range能够遍历后台传递的数据列表
{{range .aticles}} <tr> <td>{{.Aname}}</td><!--Aname是articles的属性字段--> <td><a href="/content?id={{.Id}}">查看详情</a></td> <td> {{.Atime.Format "2006-01-02 15:04:05"}}</td> <td>{{.Acount}}</td> <td><a href="/delete?id={{.Id}}" class="dels">删除</a></td> <td><a href="/update?id={{.Id}}">编辑</a></td> <td>财经新闻</td> </tr>
{{end}}
4.视图函数
问题描述:在web中,常常会遇到简单的数据运算,如分页场景,点击上一页,须要当前页减1运算。在beego中,不支持前端运算。
解决方法:beego框架提供了视图函数,解决前端运算的需求。
1.首先在main.go程序中添加视图函数,并将视图函数和key进行关联
func main() { beego.AddFuncMap("showprePage", showprePage) beego.AddFuncMap("shownextPage", shownextPage) beego.Run() } //定义视图函数 func showprePage(pageIndex int) (preIndex int) { preIndex = pageIndex - 1 return } func shownextPage(pageIndex int) (nextIndex int) { nextIndex = pageIndex + 1 return }
2.在前端引用视图函数,使用管道|引用
<a href="/index?pageIndex={{.pageIndex|showprePage}}">上一页 </a>
说明:|前的是函数的参数,整个运算的结果就是最终的返回结果
5.beego框架下的分页
问题描述:在web开发中,常常遇到分页的功能
解决方法:下面介绍一下beego框架实现分页的方法
1.后台获取总记录数
o := orm.NewOrm() //获取总数量 count, err := o.QueryTable("Article").Count() if err != nil { beego.Info("获取总数量出错", err) }
2.后台计算总页数
pageSize := 2 //每页的大小 ,一般从前端传入 pages := math.Ceil(float64(count) / float64(pageSize)) //获取总页数,并向上取整
3.查询分页的部分数据
start := (pageIndex - 1) * pageSize //计算起始的位置(当前页-1)*页大小 var articles []models.Article _, err = o.QueryTable("Article").Limit(pageSize, start).All(&articles) //Limit 第一个参数:页大小, 第二个参数:起始位置
4.前端利用视图函数,实现上一页、下一页的计算,并将当前页经过url拼接形式传入后台
<li> <a href="/index?pageIndex={{.pageIndex|showprePage}}">上一页 </a> </li> <li> <a href="/index?pageIndex={{.pageIndex|shownextPage}}">下一页</a></li>
5.后台对当前页进行处理,即超过总页数或小于等于0的状况
if pageIndex <= 0 { pageIndex = 1 } if pageIndex > int(pages) { pageIndex = int(pages) }
6.beego中cookie和session的使用
6.1 beego利用Cookie实现记住用户名
实现思路:
在用户登陆时,若是点击 记住用户名,在后台处理登陆时,获取remember是否为on
若是是,则将用户名信息设置到cookie中:
if remember == "on" { c.Ctx.SetCookie("userName", userName, 200) //设置cookie,200s过时 } else { c.Ctx.SetCookie("userName", userName, -1) //设置cookie,-1表示cookie当即失效 }
在进入登陆页面时,从cookie中获取用户名,若是有值,则跳转到登陆页面时将用户名信息返回到前台,同时返回 记住用户名选中:
userName := c.Ctx.GetCookie("userName") beego.Info("用户名:", userName) if userName != "" { c.Data["userName"] = userName c.Data["checked"] = "checked" } c.TplName = "login.html"
6.2.beego利用session实现用户状态的判断
实现思路:
首先在app.conf配置文件中开启session: sessionon=true
在用户登陆成功后,将用户名信息设置到session中
c.SetSession("userName", userName) //设置session,判断用户登陆的状态 c.Redirect("/index", 302)
用户跳转到主页以前,须要判断session中是否有值,若是没有则跳转到登陆页面:
userName := c.GetSession("userName") if userName == nil { //若是用户未登陆,跳转到登陆页面 c.Redirect("/login", 302) return }
6.3.beego利用session实现用户信息的显示和退出登陆
用户信息显示:
用户登陆成功后,将用户名信息放入session中,而后跳转到主页时再将session信息传入前端:
userName := c.GetSession("userName") c.Data["userName"] = userName
退出登陆:
在处理退出登陆的方法中,删除对应的session就能够了,而后在跳转到登陆页面:
func (c *MainController) Logout() { c.DelSession("userName") c.Redirect("/login", 302) }
==============================================go语言基础===========================================
1.go语言中切片的复制和扩容问题
go语言中,能够经过截取切片来产生新的切片,可是产生的新切片和原来的切片共享同一底层数组
如:
// 建立一个整型切片 // 其长度和容量都是 5 个元素 myNum := []int{10, 20, 30, 40, 50} // 建立一个新切片 // 其长度为 2 个元素,容量为 4 个元素 newNum := slice[1:3]
执行上面的代码后,咱们有了两个切片,它们共享同一段底层数组,但经过不一样的切片会看到底层数组的不一样部分:
若是经过append函数增长切片的新元素,若是没有超过切片的容量,那么新切片和原切片仍然共享一块内存。若是超过了容量,则会产生一个新的底层数组:
若是切片的底层数组没有足够的可用容量,append() 函数会建立一个新的底层数组,将被引用的现有的值复制到新数组里,再追加新的值,此时 append 操做同时增长切片的长度和容量:
如:
myNum := []int{10, 20, 30, 40, 50} // 建立新的切片,其长度为 2 个元素,容量为 4 个元素 newNum := myNum[1:3] // 使用原有的容量来分配一个新元素 // 将新元素赋值为 60 newNum = append(newNum, 60)
执行上面的代码后的底层数据结构以下图所示:
此时由于 newNum 在底层数组里还有额外的容量可用,append() 函数将可用的元素合并入切片的长度,并对其进行赋值。因为和原始的切片共享同一个底层数组,myNum 中索引为 3 的元素的值也被改动了。
// 建立一个长度和容量都是 4 的整型切片 myNum := []int{10, 20, 30, 40} // 向切片追加一个新元素 // 将新元素赋值为 50 newNum := append(myNum, 50)
当这个 append 操做完成后,newSlice 拥有一个全新的底层数组,这个数组的容量是原来的两倍:
函数 append() 会智能地处理底层数组的容量增加。在切片的容量小于 1000 个元素时,老是会成倍地增长容量。一旦元素个数超过 1000,容量的增加因子会设为 1.25,也就是会每次增长 25%的容量(随着语言的演化,这种增加算法可能会有所改变)。
注意:
内置函数 append() 在操做切片时会首先使用可用容量。一旦没有可用容量,就会分配一个新的底层数组。这致使很容易忘记切片间正在共享同一个底层数组。一旦发生这种状况,对切片进行修改,极可能会致使随机且奇怪的问题,这种问题通常都很难调查。若是在建立切片时设置切片的容量和长度同样,就能够强制让新切片的第一个 append 操做建立新的底层数组,与原有的底层数组分离。这样就能够安全地进行后续的修改操做了:
myFruit := fruit[2:3:3] // 向 myFruit 追加新字符串 myFruit = append(myFruit, "Kiwi")
这里,咱们限制了 myFruit 的容量为 1。当咱们第一次对 myFruit 调用 append() 函数的时候,会建立一个新的底层数组,这个数组包括 2 个元素,并将水果 Plum 复制进来,再追加新水果 Kiwi,并返回一个引用了这个底层数组的新切片。由于新的切片 myFruit 拥有了本身的底层数组,因此杜绝了可能发生的问题。咱们能够继续向新切片里追加水果,而不用担忧会不当心修改了其余切片里的水果。能够经过下图来理解此时内存中的数据结构: