Golang beego api 簡單使用以及一些容易碰到的問題

初步使用beego框架,參照了官網文檔教程,將結合自己的實際使用及個人理解,對beego api自動化文檔做個筆記。

官方鏈接 : https://beego.me/docs/intro/

一、安裝beego:命令行輸入,網絡強悍應該可以get下來,我是在$GOPATH/src下操作的。

go get github.com/astaxie/beego

二、牛皮的bee工具的安裝:

go get github.com/beego/bee

三、新建一個bee API項目:

bee api beeapi

不出意外,命令行一頓操作之後,應該在$GOPATH/src下面操作出了一個beeapi文件夾。用IDE打開這個project,可以看到如下結構:

beego app是標準的MVC三層結構,bee api只是把View去掉了。

四、稍微研究了下自動生成的Controller和對應的Models後,又經過老師的解釋,我認爲,Controller負責接受客戶端的http請求,然後models裏面的東西就負責具體的操作。Models操作完,把結果給Controller,Controller再把結果返回給客戶端。因而Controller就相當於中繼了。

接下來進行照葫蘆畫瓢,在controller和models下同時新建一個叫作weapon的go文件。

先來操作一下controller:

在“葫蘆”/controller/user.go中,看到如下代碼:


// Operations about Users
type UserController struct {
	beego.Controller
}

// @Title CreateUser
// @Description create users
// @Param	body		body 	models.User	true		"body for user content"
// @Success 200 {int} models.User.Id
// @Failure 403 body is empty
// @router / [post]
func (u *UserController) Post() {
	var user models.User
	json.Unmarshal(u.Ctx.Input.RequestBody, &user)
	uid := models.AddUser(user)
	u.Data["json"] = map[string]string{"uid": uid}
	u.ServeJSON()
}

// @Title GetAll
// @Description get all Users
// @Success 200 {object} models.User
// @router / [get]
func (u *UserController) GetAll() {
	users := models.GetAllUsers()
	u.Data["json"] = users
	u.ServeJSON()
}

不全部粘貼,相互類似。

那麼我們在自己的weapon中:

先操作出一個controller叫做WeaponController:

//Operation About Weapon,When WeaponController Contains beego.Controller,
//It Will Automaticly Poccess All beego.Controller's Methods.Sounds Like Inherit. 
type WeaponController struct {
	beego.Controller
}

再操作一下它的一些方法:

//***These comments are so bad ass, explain later***

// @Title GetAll (--This comment is title--)
// @Description get all Weapons (--This is description about this method--)
// @Success 200 {object} models.Weapon (--Success status--)
// @router / [get] (--IMPORTANT:this shows its sub-route in /v1/weapon/,(Explain //later),and its http operation is GET--)
func (w *WeaponController) GetAll() {
	//Call Model's function and get some returned value
	weapons := models.GetAllWeapons()
	//Set w.Data to returned value
	w.Data["json"] = weapons
	//Response
	w.ServeJSON()
}

// @Title GetWeapon
// @Description get weapon by id
// @Param	wid	path 	string	true  "The key for staticblock"
//About Param: variable's name, inputType(in http), dataType, is it neccessary, //description
// @Success 200 {object} models.Weapon
// @Failure 403 :wid is empty
// @router /:wid [get] (This shows its route is :/v1/weapon/:wid, and ":wid" should //be replaced with a weaponID)
func (w *WeaponController) GetWeapon(){
	wid ,err:= w.GetInt(":wid")
	if err == nil {
		weapon, err := models.GetWeapon(wid)
		if err != nil {
			w.Data["json"] = err.Error()
		} else {
			w.Data["json"] = weapon
		}
	}
	w.ServeJSON()
}

// @Title AddWeapon
// @Description create a new weapon
// @Param	body		body 	models.Weapon	true "body for weapon content"
// @Success 200 {int} models.Weapon.Id
// @Failure 403 body is empty
// @router / [post]
func (w *WeaponController) AddWeapon(){
	var weapon models.Weapon
	json.Unmarshal(w.Ctx.Input.RequestBody, &weapon)
	wid := models.AddWeapon(&weapon)
	w.Data["json"] = map[int]int{wid: wid}
	w.ServeJSON()
}

然後是,models:

//This part is meant to process logic tasks or other things, MVC-M.Convenient to //manage project
//This part usually define a type of some resource,such as "Weapon",then do all the //detailed work
//controller tells to do, and give back a specific result to its controller's method

//Define a WeaponList with key=weapons'id to store all the weapons
var WeaponList map[int] *Weapon
//Define what does a weapon have
type Weapon struct {
	Id int
	Name string
	Range int
	Type string
	Mags int
	Weight int
}

//initialization: Add a sample of weapon
func init(){
	WeaponList = make(map[int] *Weapon)
	w := Weapon{
		201801,
		"Desert.Eagle",
		50,
		"pistol",
		7,
		600,
	}
	WeaponList[w.Id] = &w
}

//Return all weapons in WeaponList
func GetAllWeapons() map[int] *Weapon{
	return WeaponList
}

//Select a specific weapon from WeaponList by its Id
func GetWeapon(wth int) (*Weapon,error){
	if w, ok :=WeaponList[wth];ok {
		return w, nil
	}
	return nil,errors.New("No such Weapon!")
}

//Add a brand new kind of weapon to WeaponList
func AddWeapon(w *Weapon) int{
	WeaponList[w.Id]=w
	return w.Id
}

好了,現在開始把所有的東西串起來了:

點開terminal,在當前項目目錄下面:

操作這個

bee run -gendoc=true -downdoc=true

 

 

然後等他操作。。。

操作完成後,我們注意到,工程目錄下多了一個swagger文件夾。還有routers目錄下面多了一個comment。。。go文件,打開這個comment...go:裏面有很多長得很像的東西:

	beego.GlobalControllerRouter["beeapi2/controllers:UserController"] = append(beego.GlobalControllerRouter["beeapi2/controllers:UserController"],
		beego.ControllerComments{
			Method: "Logout",
			Router: `/logout`,
			AllowHTTPMethods: []string{"get"},
			Params: nil})

仔細觀察,厲害了,他好像是根據我們之前的bad ass註釋生成的,router.go裏面解釋了爲什麼之前的註釋裏面寫的路徑在“/v1/weapon/”下面,這是遵循了RESTful風格定的名字和路徑。

五、最後,在瀏覽器:localhost:8080/swagger,摸索一下你就會發現,這裏就是測試你寫的beego api的地方。

 

 

-------------------------------------------------

我遇到過的問題:

1、beego如果發現修改了API,重新bee run -gendoc=true之後而swagger並沒有更新改變,請清除瀏覽器的緩存(或chrome的Ctrl+F5)再試。WC這個坑了我好久好多次。。。

2、ONE: beego用bee run -gendoc=true 沒有生成路由go文件或更新生成的swagger, 或者在訪問API的時候報404 not found:在配置文件中改成dev模式。。。

     TWO: 檢查-gendoc=true拼寫是否正確。

------------------------------------------------

3、又發現一個坑:我修改了controller的一個小邏輯,又打了個log,但無論重新go build 還是 bee run -gendoc=true ,最後在調這個controller的這個 API 時,改過的邏輯並沒有改變,而且log也沒有打出來,刪除可執行文件再試還是沒改。。。靈異事件?最後我把router_comment刪了,重新bee run -gendoc=true就好了。

4、又更新一個稍不注意就會遇到並覺得十分詭異的坑:swagger上面的api點擊之後調用的卻是另一個api, 呈現調用錯位的錯覺,且沒有什麼規律。原因:controller裏面的路由註釋中的@Title部分出現了重複。beego swagger使用Title來指定唯一映射。解決方法:將所有的Title重寫成唯一的,或者乾脆將所有的Title給刪除了,對沒錯,可以不用寫Title。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章