page contents

浅析GO语言中的beego框架

beego是一个快速开发Go应用的http框架,作者是SegmentFault 用户,go 语言方面技术大牛。beego可以用来快速开发API、Web、后端服务等各种应用,是一个 RESTFul的框架,主要设计灵感来源于 tor...

attachments-2021-07-tR4ggYjK60f4e05fb33c9.png

beego是一个快速开发Go应用的http框架,作者是SegmentFault 用户,go 语言方面技术大牛。beego可以用来快速开发API、Web、后端服务等各种应用,是一个 RESTFul的框架,主要设计灵感来源于 tornado、sinatra、 flask这三个框架,但是结合了Go本身的一些特性(interface、struct继承等)而设计的一个框架。

架构

beego是基于八大独立的模块之上构建的,是一个高度 解耦的框架。当初设计beego的时候就是考虑功能模块化,用户即使不适用beego的http逻辑,也是可以在使用这些独立模块,例如你可以使用cache模块来做你的缓存逻辑,使用日志模块来记录你的操作信息,使用 config模块来解析你各种格式的文件,所以不仅仅在beego开发中,你的socket游戏开发中也是很有用的模块,这也是beego为什么受欢迎的一个原因。大家如果玩过乐高的话,应该知道很多高级的东西都是一块一块的积木搭建出来的,而设计beego的时候,这些模块就是积木,高级机器人就是beego。至于这些模块的功能以及如何使用会在后面的文档会逐一介绍。

执行逻辑

既然beego是基于这些模块构建的,那么他的执行逻辑是怎么样的呢?beego是一个典型的MVC架构,他的执行逻辑如下图所示:

项目结构

一般的beego项目的目录如下所示:

├── conf
│ └── app.conf
├── controllers│
├── admin
│ └── default.go
├── main.go
├── models
│ └── models.go
├── static│
├── css│
├── ico
│ ├── img
│ └── js└── views
├── admin
└── index.tpl

从上面的目录结构我们可以看出来M(models目录)、V(views目录)、C(controllers目录)的结构,main.go是入口文件。

选择 Go 语言

断断续续看了 Go 几个星期了,讲真的真是喜欢的不得了。认真学过之后,你会觉得非常的优雅,写东西很舒服。学习 Go 我觉得很有必要的是,Go 中自带的数据结构很少,类似于 List 或者 Tree 之类的,最好尝试一下如何去设计一些常用的数据结构。话说回来,Go 的出身始终是一门后端语言。我非常后悔用 Flask 或者 Django 来作为我的后端入门框架或者选择。封装的太好了,往往对于一个入门新手来说学习不到什么。

而 Go 就不一样了,它天生被设计是一门后端语言。也就是说,你将会学习到非常多的后端知识。看看下面这一张图,当时我看着就有一种很过瘾的感觉,因为这些知识你都知道,但是作为一个后端开发者你没有去了解过,这是非常大的失误。并不是想去用学习好 Go 去弥补没有学习好 C++ 的遗憾,只是新生事物,多尝试尝试总是极好的,哪怕只是浅尝辄止。Go 作为一门新的语言,其语言设计的特性,背后 Google 爸爸的撑腰以及现在 Docker 技术发展,前景应该还是不错的。所以如果你是编程新手或者是想入门后端的开发者,我强烈建议你选择 Go 语言。

语言学到最后,框架总是少不了的。虽然不能完全依赖框架,但是还是可以学习一下框架的设计思想。对于 Beego 框架的评价总是各种各样,这也要看自己的选择了。之所以选择 Beego 框架来入门,主要是因为其详细的文档以及教程示例非常多。

Go Web 初探

先看一下最基本的 Go 中的 web 服务,只用到了 Go 中的 net/http 这个包:

package main
 
    import (
        "fmt"
        "net/http"
        "strings"
        "log"
    )
 
    func sayhelloName(w http.ResponseWriter, r *http.Request) {
        r.ParseForm()  //解析参数,默认是不会解析的
        fmt.Println(r.Form)  //这些信息是输出到服务器端的打印信息
        fmt.Println("path", r.URL.Path)
        fmt.Println("scheme", r.URL.Scheme)
        fmt.Println(r.Form["url_long"])
        for k, v := range r.Form {
            fmt.Println("key:", k)
            fmt.Println("val:", strings.Join(v, ""))
        }
        fmt.Fprintf(w, "Hello astaxie!") //这个写入到w的是输出到客户端的
    }
 
    func main() {
        http.HandleFunc("/", sayhelloName) //设置访问的路由
        err := http.ListenAndServe(":9090", nil) //设置监听的端口
        if err != nil {
            log.Fatal("ListenAndServe: ", err)
        }
    }

执行 go run web.go根据提示在浏览器地址栏打开 URL ,如下图所示:

安装 Go 以及 Beego

基本的你得有个 Go 语言的环境,安装什么的就不讲了。只是最后配置其环境变量许多人都容易弄错,包括我自己也是。其实多次也能够配置好,只是每次重新启动就提示上次的配置无效,也不知道是怎么回事。讲一下安装 Beego 框架

export GOBIN="/usr/local/go/bin"
export GOPATH="/Users/allenwu/GoProjects"
export PATH="$PATH:$GOBIN:$GOPATH/bin"

在终端输入如上所示代码,其中 allenwu 替换成你自己的 username,并且在根目录下创建 GoProjects 文件夹,作为下一步工作目录。配置好之后,输入如下命令确保保存成功:

source ~/.zshrc

最后当然要测试一下环境变量是否配置成功,在 shell 中输入 go env若如下所示即表明成功(着重注意一下的就是 gopath 是不是为空):

配置环境没问题之后,就是安装 go 和 bee 工具了:

$ go get github.com/astaxie/beego
$ go get github.com/beego/bee

检查安装是否成功,启动一个 Hello world级别的 App:

$ cd $GOPATH/src
$ bee new hello
$ cd hello
$ bee run hello

会提示你在浏览器输入地址,然后就能知道是否安装成功啦。

体验 Beego 框架

安装好 Beego 框架之后,官方给了三个 samples,我们选择其中一个来进行入门体验一下。如下实例选择的是 todo App。我们将 clone 下来的 todo App 放置到指定目录下,用 sublimeText3 打开这个示例项目,强烈建议你打开侧边栏设置选项。

本的结构之后,我们启动这个 App。我们采用 Beego 提供的工具 bee 来启动。进入到最终的指定文件夹 todo 之后,执行 bee run 命令。

可以看到打印出一个 Bee 的 Logo,表示启动成功了,稍等一下就会继续提示你在浏览器中输入指定 IP 地址和端口号,也就是如下所示。

官方讲这个小 App 结合了 Angular ,体验还是挺不错的。接下来我们来简单分析一下示例 App 的代码结构。首先入口程序是 Main.go,这是想都不用想的,一个程序员的直觉:

package main
 
import (
"github.com/astaxie/beego"
  // 注释一
"samples/todo/controllers"
)
 
func main() {
  // 注释二
beego.Router("/", &controllers.MainController{})
beego.Router("/task/", &controllers.TaskController{}, "get:ListTasks;post:NewTask")
beego.Router("/task/:id:int", &controllers.TaskController{}, "get:GetTask;put:UpdateTask")
  // 注释三
beego.Run()
}

我们第一感觉还是看到 Main() 函数,看到了 Router() 函数,有一些 web 开发或者开发经验的应该都知道这是路由机制。对应的是 url 与 Controller。在 MVC 框架中 Controller 是一个很重要的概念了。我们自然下一步骤就是去往 Controller 中看看:

package controllers
 
import (
"github.com/astaxie/beego"
)
// 注释一
type MainController struct {
beego.Controller
}
// 注释二
func (this *MainController) Get() {
  // 注释三
this.TplName = "index.html"
this.Render()
}

在看完 Go 的基本语法之后,看到注释一应该也能明白一个一二三四了,我们声明了一个控制器 MainController,这个控制器里面内嵌了 beego.Controller,这就是 Go 的嵌入方式,也就是 MainController 自动拥有了所有 beego.Controller 的方法。而 beego.Controller 拥有很多方法,其中包括 Init、Prepare、Post、Get、Delete、Head等 方法。我们可以通过重写的方式来实现这些方法,而我们上面的代码就是重写了 Get 方法。

在注释三处,我们看到了 index.html,应该明白了 Get 方法去获取对应名称的 HTML 文件,并进行渲染。到这里我们很简单的讲述了一下 MVC 中的 V 和 C,发现没,Model 竟然不知道从哪去讲。还请回头看看 Main.go 中的注释二处:

beego.Router("/task/", &controllers.TaskController{}, "get:ListTasks;post:NewTask")

上述路由引导我们进入了 TaskController 这个控制器来了,我们分析一下下面这个文件:

package controllers
 
import (
"encoding/json"
"strconv"
 
"github.com/astaxie/beego"
"samples/todo/models"
)
 
type TaskController struct {
beego.Controller
}
 
// Example:
//
//   req: GET /task/
//   res: 200 {"Tasks": [
//          {"ID": 1, "Title": "Learn Go", "Done": false},
//          {"ID": 2, "Title": "Buy bread", "Done": true}
//        ]}
func (this *TaskController) ListTasks() {
res := struct{ Tasks []*models.Task }{models.DefaultTaskList.All()}
this.Data["json"] = res
this.ServeJSON()
}

很明显我们看到了 models 关键字,并且调用了其中的 Task ,我们选择进入 Task.go 文件看看:

package models
 
import (
"fmt"
)
 
var DefaultTaskList *TaskManager
 
// Task Model
type Task struct {
ID    int64  // Unique identifier
Title string // Description
Done  bool   // Is this task done?
}
 
// NewTask creates a new task given a title, that can't be empty.
func NewTask(title string) (*Task, error) {
if title == "" {
return nil, fmt.Errorf("empty title")
}
return &Task{0, title, false}, nil
}
 
// TaskManager manages a list of tasks in memory.
// 注释一
type TaskManager struct {
tasks  []*Task
lastID int64
}
 
// NewTaskManager returns an empty TaskManager.
func NewTaskManager() *TaskManager {
return &TaskManager{}
}
 
// Save saves the given Task in the TaskManager.
func (m *TaskManager) Save(task *Task) error {
if task.ID == 0 {
m.lastID++
task.ID = m.lastID
m.tasks = append(m.tasks, cloneTask(task))
return nil
}
 
for i, t := range m.tasks {
if t.ID == task.ID {
m.tasks[i] = cloneTask(task)
return nil
}
}
return fmt.Errorf("unknown task")
}
 
// cloneTask creates and returns a deep copy of the given Task.
func cloneTask(t *Task) *Task {
c := *t
return &c
}
 
// All returns the list of all the Tasks in the TaskManager.
func (m *TaskManager) All() []*Task {
return m.tasks
}
 
// Find returns the Task with the given id in the TaskManager and a boolean
// indicating if the id was found.
func (m *TaskManager) Find(ID int64) (*Task, bool) {
for _, t := range m.tasks {
if t.ID == ID {
return t, true
}
}
return nil, false
}
 
func init() {
DefaultTaskList = NewTaskManager()
}

如上所示的 task Model 主要就是定义了 task 这个实体该有的成员变量。以及一个 taskManager 来管理这些 task,其整体结构在理解了 Go 语言的一些基本的机制之后还是比较简单的。

在之前的整个实例结构中,我们还看到了如下所示的静态文件,它们的作用就很明显啦:

├── static
    │   ├── css
    │   ├── img
    │   └── js

好了,以上就是 Go 的一个框架 Beego 的入门实例了,其实很简单。我也只是简单的写一下入门的东西。后续研究一下 Go 的自动化 API 构建。往后继续学习 Go 和 Docker 的结合应用吧。

更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。

程序员编程交流QQ群:805358732

如果你想用Python开辟副业赚钱,但不熟悉爬虫与反爬虫技术,没有接单途径,也缺乏兼职经验
关注下方微信公众号:Python编程学习圈,获取价值999元全套Python入门到进阶的学习资料以及教程,还有Python技术交流群一起交流学习哦。

attachments-2022-06-9M3G5ZV662ad4297aa1c5.jpeg

  • 发表于 2021-07-19 10:16
  • 阅读 ( 634 )
  • 分类:Golang

0 条评论

请先 登录 后评论
轩辕小不懂
轩辕小不懂

2403 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1470 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章