分页是web页面中常见的功能实现。下面来用一个简单的例子说明一个实现的方法。
首先这只是一个例子,所以就不用从数据库里读取数据那么麻烦了。声明一个切片,把全部数据都放这里,用来代替数据库里的全部数据了。
//全部数据
var dataAll = []string{}
也没时间去搜罗数据,就自动生成好了。为了省事,就用unicode编码随机汉字了。(这样会出现很多生僻字哦)
//自动生成全部数据
if len(dataAll)<20 {
for i := 0; i < 99; i++ {
aString := ""
rand.Seed(time.Now().UnixNano())
aNum := rand.Intn(5)+5
for j:=0; j<aNum; j++{
rand.Seed(time.Now().UnixNano())
time.Sleep(time.Nanosecond)
aString += string(19968+rand.Int63n(40869-19968))
}
dataAll = append(dataAll, strconv.Itoa(i+1)+"、"+aString)
}
}
还需要有存放当前显示数据的地方、当前的页码、每页显示的记录数
//当前显示数据
var dataNow = []string{}
//当前页码
var pageNum = 0
//每页显示记录数
var recordPerPage = 5
我就设置成每页都显示 5 条记录吧。实际情况,可以随时修改,或者从传递来的参数中获取。
当前页码一定是传递来的参数,因为要分页,所以一定是传递来的。我这里就用显式的获取方式。
//获取当前页码
pageNum,err := strconv.Atoi(request.FormValue("page"))
if err != nil{
pageNum = 0
}
如果获取出现错误,就把当前页设置为第一页 pageNum = 0
获取当前显示的数据略有些小技巧。你需要处理如果当前页码超出了总页码范围的情况。我这里都把页面跳转为第一页。
//获取当前显示数据
if pageNum * recordPerPage >= len(dataAll) || pageNum * recordPerPage < 0{
pageNum = 0
}
for i := 0; i < recordPerPage && (pageNum * recordPerPage + i)< len(dataAll); i++ {
dataNow = append(dataNow, dataAll[pageNum * recordPerPage + i])
}
这时候,已经获取到界面显示的主要内容了,就是 dataNow。不过,还需要分页控制啊,所以还要建立分页数据。首页、上页、下页、末页
//分页数据
var firstPage = 0
var lastPage = len(dataAll)/recordPerPage
if lastPage*recordPerPage < len(dataAll) {
lastPage++
}
var nextPage = pageNum + 1
var prePage = pageNum - 1
不用担心 nextPage 和 prePage 超出范围,因为前面的代码已经处理过超出后的情况了。
下面为了把记录和分页数据都传递到页面上,先把分页数据组合成一个映射
var page4 = map[string]int{"firstpage":firstPage,"lastpage":lastPage-1,"nextpage":nextPage, "prepage":prePage, "currentpage":pageNum+1}
当然为了也能够表现当前页,还增加了一个 currentpage。
之后当然是把全部要传递到页面的数据都组织起来。因为数据结构比较复杂,这里需要 interface 类型来担当数据类型。
var dataReturn = map[string]interface{}{"listData":dataNow,"pageData":page4}
好了,模板页面就是要绑定 dataReturn 了。
t, _ := template.ParseFiles("./JoelTemplate/sayHelloTurnPage.html")
t.ExecuteTemplate(writer, "page", dataReturn)
我的模板是 sayHelloTurnPage.html
看一下完整代码吧
//全部数据
var dataAll = []string{}
func Joeltemplate10(writer http.ResponseWriter, request *http.Request) {
//当前显示数据
var dataNow = []string{}
//当前页码
var pageNum = 0
//每页显示记录数
var recordPerPage = 5
//自动生成全部数据
if len(dataAll)<20 {
for i := 0; i < 99; i++ {
aString := ""
rand.Seed(time.Now().UnixNano())
aNum := rand.Intn(5)+5
for j:=0; j<aNum; j++{
rand.Seed(time.Now().UnixNano())
time.Sleep(time.Nanosecond) //电脑运算太快了,短暂休眠避免随机汉字重复
aString += string(19968+rand.Int63n(40869-19968))
}
dataAll = append(dataAll, strconv.Itoa(i+1)+"、"+aString)
}
}
//获取当前页码
pageNum,err := strconv.Atoi(request.FormValue("page"))
if err != nil{
pageNum = 0
}
//获取当前显示数据
if pageNum * recordPerPage >= len(dataAll) || pageNum * recordPerPage < 0{
pageNum = 0
}
for i := 0; i < recordPerPage && (pageNum * recordPerPage + i)< len(dataAll); i++ {
dataNow = append(dataNow, dataAll[pageNum * recordPerPage + i])
}
//分页数据
var firstPage = 0
var lastPage = len(dataAll)/recordPerPage
if lastPage*recordPerPage < len(dataAll) {
lastPage++
}
var nextPage = pageNum + 1
var prePage = pageNum - 1
var page4 = map[string]int{"firstpage":firstPage,"lastpage":lastPage-1,"nextpage":nextPage, "prepage":prePage, "currentpage":pageNum+1}
var dataReturn = map[string]interface{}{"listData":dataNow,"pageData":page4}
t, _ := template.ParseFiles("./JoelTemplate/sayHelloTurnPage.html")
t.ExecuteTemplate(writer, "page", dataReturn)
}
然后在 main 函数中
http.HandleFunc("/page/", JoelTempFunc.Joeltemplate10)
server := http.Server{Addr:":8090"}
server.ListenAndServe()
我的模板是这样的
{{define "page"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Go Web Programming</title>
</head>
<body>
分页啦
<hr>
{{range .listData}}
{{.}}<br>
{{end}}
<a href="?page={{.pageData.firstpage}}">首页</a>
<a href="?page={{.pageData.prepage}}">上页</a>
<a href="?page={{.pageData.nextpage}}">下页</a>
<a href="?page={{.pageData.lastpage}}">末页</a>
当前页:{{.pageData.currentpage}}
</body>
</html>
{{end}}
很简单的模板,只为了说明问题。
运行效果如下图
当你在末页的情况下,还点击下页的时候,会跳转到第1页。
在首页的情况下,还点击上页的时候,页面会留在首页。
这个例子已经能在大多数情况下使用了。