服務計算——web開發個人專案總結
專案總結
姓名:王迎旭
學號:16340226
分工:後端
主要負責:handler函式的完善 以及 在本地的測試
主要工作
這次專案自己完成了部分後端程式碼的補充工作,基於 天揚dalao 已經搭好的框架 和 澤浩dalao 已經給出的示例,自己繼續再進行操作工作就變得簡單很多了,比如:
基於函式peopleIdHandler()
,完成後面vehicle
、starship
、planet
、flims
等操作
func peopleIdHandler(formatter *render.Render,db *bolt.DB) http.HandlerFunc{
return func(w http.ResponseWriter, req *http.Request){
vars := mux.Vars(req)
// 獲取id
id := vars["id"]
// 從db中獲得Person Struct
v, err := dbOperator.GetElementById(db, "Person", id)
if err != nil {
fmt.Println(err)
// WriteResponse(w, ErrorResponseCode, "failed", nil)
formatter.Text (w, http.StatusOK, "HTTP/1.0 "+ErrorResponseCode+" Not Found\n")
} else {
var user swapi.Person
err = json.Unmarshal(v, &user)
if err != nil {
fmt.Println(err)
} else {
formatter.Text(w, http.StatusOK, "HTTP/1.0 "+SuccessResponseCode+" OK\n")
formatter.Text(w, http.StatusOK, "Content-Type: application/json\n")
formatter.JSON(w,http.StatusOK,user)
}
}
}
}
這部分的工作就是我們可以實現,在捕獲到請求之後,返回對應的 某物對應ID
的json
資訊,如果找到就可以成功顯示並給出提示資訊,如果不能,就顯示報錯:
如輸入指令http://localhost:3000/api
,訪問 root
:
HTTP/1.0 200 OK
Content-Type: application/json
{
"films": "http://localhost:3000/api/films/",
"people": "http://localhost:3000/api/people/",
"planets": "http://localhost:3000/api/planets/",
"species": "http://localhost:3000/api/species/",
"starships": "http://localhost:3000/api/starships/",
"vehicles": "http://localhost:3000/api/vehicles/"
}
測試部分
在完成函式的書寫之後,在本地的測試也遇到了一點問題:
- 輸入訪問指令之後,
git bash
顯示網頁已經成功響應,但是並不能在主介面上顯示對應的資訊 - 缺少對應庫檔案,編譯路徑衝突
- 8080 埠被佔用
針對上面的問題,自己也是嘗試進行了解決:
- 從新將已經
push
到github
上的程式碼clone
到本地的/gowork/src/github.com/
路徑下,從新進行編譯,這次再次輸入訪問指令,git bash
成功響應,chrome
成功返回對應資訊;不過還不是很清楚,為什麼在桌面上放置的安裝包,成功編譯之後無法在chrome
上顯示 - 對於缺少庫檔案的問題,只能在
/gowork/src/github.com/
路徑下慢慢安裝了,不過建議以後import
時候,注意小組成員之間統一路徑寫法 - 對於 8080 埠被佔用的問題,可以開啟命令列強行
kill
掉佔用 8080 埠的程序
對於boltdb資料庫知識的學習
大二下學年學習過 postgresql
如何使用,但是並沒有真正的跟實際的程式設計聯絡起來,這次接著完成專案的機會,自己也是對boltdb
進行了一點了解,首先是boltdb
非常適合於Go
專案程式設計對資料庫操作的需要,同時非常適合我這樣的小白初次接觸使用。
- 首先在
Go
庫中安裝boltdb
go get github.com/boltdb/bolt
- 建立資料庫
db, err := bolt.Open("my.db", 0600, nil)
這裡的Open
的引數,與 c++
的引數設定比較像,第一個為資料庫的路徑,如果不存在則建立新的資料庫,第二個引數為檔案操作,第三個引數為可選引數;
- 讀寫操作
err := db.Update(func(tx *bolt.Tx) error {
...
return nil
})
err的返回值報告導致您的事務不能完成的所有磁碟故障
- 批量讀寫事物
每一次新的事物都需要等待上一次事物的結束,這種開銷我們可以通過DB.Batch()
批處理來完成
err := db.Batch(func(tx *bolt.Tx) error {
...
return nil
})
在批處理過程中如果某個事務失敗了,批處理會多次呼叫這個函式函式返回成功則成功。如果中途失敗了,則整個事務會回滾。
- 啟動事務
DB.Begin()
啟動函式包含在db.update
和db.batch
中,該函式啟動事務開始執行事務並返回結果關閉事務.
// Start a writable transaction.
tx, err := db.Begin(true)
if err != nil {
return err
}
defer tx.Rollback()
// Use the transaction...
_, err := tx.CreateBucket([]byte("MyBucket"))
if err != nil {
return err
}
// Commit the transaction and check for error.
if err := tx.Commit(); err != nil {
return err
}
- 使用
資料結構
桶
桶是資料庫中鍵/值對的集合。桶中的所有鍵必須是唯一的。可以使用DB.CreateBucket()
建立一個桶:
db.Update(func(tx *bolt.Tx) error {
b, err := tx.CreateBucket([]byte("MyBucket"))
if err != nil {
return fmt.Errorf("create bucket: %s", err)
}
return nil
})
也可以使用Tx.CreateBucketIfNotExists()
來建立桶,該函式會先判斷是否已經存在該桶不存在即建立, 刪除桶可以使用Tx.DeleteBucket()
來完成
- 使用
k-v
對
儲存鍵值對到桶裡可以使用Bucket.Put()
來完成:
db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("MyFriendsBucket"))
err := b.Put([]byte("one"), []byte("zhangsan"))
return err
})
獲取鍵值Bucket.Get()
:
db.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("MyFriendsBucket"))
v := b.Get([]byte("one"))
fmt.Printf("The answer is: %s\n", v)
return nil
})
get()
函式不返回一個錯誤,因為它的執行是保證工作(除非有某種系統故障)。如果鍵存在,那麼它將返回它的值。如果它不存在,那麼它將返回nil。
還需要注意的是當事務開啟都get返回的值時唯一有效的,如果需要將該值用於其他事務,可以通過copy
拷貝到其他的byte slice
中
- 迴圈遍歷桶
如果你知道所在桶中擁有鍵,你也可以使用ForEach()來迭代:
db.View(func(tx *bolt.Tx) error {
// Assume bucket exists and has keys
b := tx.Bucket([]byte("MyBucket"))
b.ForEach(func(k, v []byte) error {
fmt.Printf("key=%s, value=%s\n", k, v)
return nil
})
return nil
})