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。

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