1.Abstract
在學習web開發的過程中會遇到很多困難,因此寫一篇類似綜述類的文章。作為路線圖,從web開發要素的index出發,來介紹golang開發的學習流程以及Example代碼。在描述中多是使用代碼來描述使用方法不會做過多的說明。最後可以方便地copy代碼來實現自己的需求。
本文適應對象: 對web開發有一定經驗的人 能夠靈活使用ajax的人(至少懂得前後分離) golang web 開發有一定瞭解,至少略讀過一些golang web開發的書籍
看完本文之後您會收穫: golang web開發的一些技巧 golang web開發的一些實用API
本文在描述的時候為瞭解釋盡量詳細,已經把解釋寫到代碼注釋中。
2.golang web 開發check list
略過的部分:基本流程式控制制,OOP等基礎文法知識。 2.1本章節提供golang web開發的知識面參考。 1.Abstract 2.golang web 開發check list 2.1 本章節提供golang_web開發的知識面參考。 3.路由器 3.1 手動路由 3.2 手動路由的綁定 3.2.1 靜態檔案 3.2.2 固定函數與資源擷取 4.頁面載入 4.1 純靜態頁(HTML) 4.2 模板頁面的載入 5.展示層指令碼 5.1 require.js 5.1.1 載入 5.1.2 頁面Business 5.2 JQuery 6.業務層 7.持久層 7.1 Mysql 7.2 Mongodb 8.單元測試注意事項 9.LOG 總結 3.路由器
路由器是整個網站對外的靈魂,如果路由做的不好URL會非常噁心。
所以這部分設計成第一個要說的內容。
路由分兩種一種是手動路由為了通過tul調度固定的功能,另外一點就是資源
的擷取,通過url的分析來模仿靜態頁的方式來擷取資源(類似get)
自動路由,主要使用OOP的COMMAND模式來實現。所有功能使用post,
統一入口,方便許可權管理,安全管理,跨域管理。但是如此強大的功能還是
交給架構來做吧。這裡就不給新手做參考了。 3.1手動路由
1 2 3 4 5 6 7 8 9 10 11 12 |
package main import ( "log" "net/http" ) func main() { RouterBinding() // 路由綁定函數 err := http.ListenAndServe( ":9090" , nil) //設定監聽的連接埠 if err != nil { log.Fatal( "ListenAndServe: " , err) } } |
在httpserver運行之前先綁定路由 3.2 手動路由的綁定 3.2.1 靜態檔案
1 |
http.Handle( "/pages/" , http.StripPrefix( "/pages/" , http.FileServer(http.Dir( "./pages" )))) |
3.2.2 固定函數與資源擷取
他們都是一樣的
1 |
http.HandleFunc( "/images/" , fileUpload.DownloadPictureAction) |
4.頁面載入
4.1 純靜態頁(HTML)
直接交給路由就行了。自動就訪問那個檔案夾了。不過生產環境果然還得是cdn,如果自己伺服器比較多。可以nginx反向 Proxy。
主要好處前後分離,能上CDN就是通訊次數多了。不過通過最佳化改善之類的都還ok啦。 4.2 模板頁面的載入僅提供關鍵代碼。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
commonPage, err := template.ParseFiles( "pages/common/head.gtpl" , //載入模板 "pages/common/navbar.gtpl" , "pages/common/tail.gtpl" ) if err != nil { panic(err.Error()) } navArgs := map[string]string{ "Home" : "home" , "User" : "yupengfei" } //複雜的參數開始往裡塞 knowledgePage, err := template.ParseFiles( "pages/knowledge/knowledge.gtpl" ) knowledgeArgs := map[string] interface {}{ "Head" : "This is a test title" , "Author" : "kun.wang" , "PublishDatetime" : "2014-09-14" , "Content" : template.HTML( "<p style=\"text-indent: 2em\">為什麼要用語義呢。</p>" )} //不是不好,只是做字串分析會影響工程效率 commonPage.ExecuteTemplate(w, "header" , nil) // render 開始 commonPage.ExecuteTemplate(w, "navbar" , navArgs) knowledgePage.ExecuteTemplate(w, "knowledge" , knowledgeArgs) commonPage.ExecuteTemplate(w, "tail" , nil) |
僅提供關鍵代碼。 字串數組作為輸入參數差錯比較困難 總結:雖然減少的通訊次數,但是沒辦法上CDN蛋疼,另外,模板的mapping蛋疼。
5.展示層指令碼
展示層指令碼做的比較困難也不是很好學。
但是一旦搞定了,代碼的複用性會有非常可觀的提升。
就普通情況而言JS開發效率是非常高的靈活度高,並且使用的是用戶端的cpu
效能好,免費資源多,學習的人也多,好招聘。 5.1 require.js 5.1.1 載入
1 |
<script data-main= "/reqmod/login_main" language= "JavaScript" defer async= "true" src= "js/r.js" ></script> |
整個網頁之留這麼一個載入指令碼的入口(每個頁面最好只有一個js檔案)
好處 js是消極式載入。不會出現網頁卡死的情況 最大化使用緩衝。(HTTP 304) 一個網頁只用一個js dom事件綁定,不用在html控制項上寫js綁定了
壞處 學習比較難 網站更新始終有緩衝沒更新的瀏覽器。造成錯誤(所以有些情況客戶自己就知道多重新整理幾次了,已經成使用者習慣了)
參數解釋 `data-main` 商務邏輯入口,載入當前字串.js這個檔案 `language` 不解釋 `defer async` 字面意思 `src` r.js就是require.js的意思。代碼到處都能搞到。 5.1.2 頁面Business
載入依賴檔案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
require.baseUrl = "/" require.config({ baseUrl: require.baseUrl, paths: { "jquery" : "js/jquery-1.10.2.min" , "domready" : "reqmod/domReady" , "pm" : "reqmod/pmodal" , "cookie" : "reqmod/cookie" , "user" : "reqmod/user" , "bootstrap" : "reqmod/bootstrap.min" , "nav" : "reqmod/nav" }, shim: { 'bootstrap' : { deps: [ 'jquery' ] } } }); //直接copy全搞定。 |
執行頁面business
執行裡面做的最多的就是dom跟事件綁定而已。載入各種js庫直接引用。
代碼美觀,開發效率,執行效率都是非常棒的。
1 2 3 4 5 6 7 8 |
require([ 'nav' , 'domready' , 'jquery' , 'user' , 'pm' ], function (nav,doc, $, user,pm){ //這個函數的第一個`數組`參數是選擇的依賴的模組。1. 網站絕對路徑。 2. 使用載入相依模組的時候選擇export的內容 //數組的順序要跟function順序一致,如果有兩個模組依賴比如說jquery外掛程式,就寫道最後不用變數,直接使用`$` doc( function () { // domReady pm.load(); //載入各種外掛程式HTML模板之類的都ok $( '#btn_login' )[ 0 ].onclick = function (){user.login();} //button 事件綁定 }); }); |
頁面MODEL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
define([ 'jquery' , 'reqmod/cookie' , 'user' , 'bootstrap' ], function ($,cookie,user){ //define 函數的參數內容require是一樣的。 // 這裡依賴的模組要在調用此模組中的模組中有path配置。不然會死的很慘,報錯的時候不會說缺少什麼什麼地方錯了。 var nav_load = function () { // 注意函數定義的方式copy就行 $. get ( '/nav.html' , function (result){ var newNode = document.createElement( "div" ); newNode.innerHTML = result; $( 'body' )[ 0 ].insertBefore(newNode,$( 'body' )[ 0 ].firstChild); //document.body.innerHTML = result + document.body.innerHTML; $( '#btn_login' )[ 0 ].onclick = function (){user.login();} $( '#btn_reg' )[ 0 ].onclick = function (){window.location= '/register.html' } $.post( '/login_check' ,{}, function (data){ if (data== |