==============================================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 擁有了本身的底層數組,因此杜絕了可能發生的問題。咱們能夠繼續向新切片裏追加水果,而不用擔憂會不當心修改了其餘切片裏的水果。能夠經過下圖來理解此時內存中的數據結構: