предисловие
Возможно, фреймворк beego должен стать первым выбором для многих PHP-специалистов, желающих перейти в Китай, потому что beego MVC, ORM и полная документация на китайском языке делают PHP-разработчиков удобными, и я в этом не сомневаюсь. Это похоже на использование ThinkPHP, когда я начал работать с PHP.
Может быть, с улучшением вашего познания вы теперь будете ненавидеть вещи. Например, однажды вы можете постепенно начать ненавидеть beego, вы обнаружите, что на языке гоСумкаРеальный смысл, вы начинаете размышлять о том, действительно ли MVC подходит для go, или вы начинаете чувствовать, что ORM безвкусна в статических языках и так далее. Я просто хочу сказать: "Может быть, ты повзрослел~". Но это не важно, у каждой популярной вещи, естественно, есть место, где мы можем учиться. Сегодняшняя статья очень проста, как заметка, в которой фиксируется мое время на чтение исходного кода beego за последние несколько дней.
Как читать фрейм?
Само собой разумеется, что фреймворк go такой же, как и фреймворк PHP:
- Загрузка конфигурации: Как загрузить файлы конфигурации.
- маршрутизация: проанализируйте, как платформа выполняет соответствующий бизнес через URI.
- ORM: как реализован ORM.
Здесь (1.) и (3.) не что иное, как загрузка файла и реализация парсера sql, я его проигнорирую, и сосредоточусь на реализации роутинга.
Установить
Просто принесите:
// Step1: 安装beego
go get github.com/astaxie/beego
// Step2: 安装bee
go get github.com/beego/bee
// Step3: 用bee工具创建一个新的项目
bee new beego-code-read
анализ кода
go имеет свой собственный http-пакет, и большинство фреймворков go также основаны на этом http-пакете, так что давайте добавим или пересмотрим этот пункт знаний, прежде чем смотреть beego. следующее:
Как запустить http сервер в go
package main
import (
// 导入net/http包
"net/http"
)
func main() {
// ------------------ 使用http包启动一个http服务 方式一 ------------------
// *http.Request http请求内容实例的指针
// http.ResponseWriter 写http响应内容的实例
http.HandleFunc("/v1/demo", func(w http.ResponseWriter, r *http.Request) {
// 写入响应内容
w.Write([]byte("Hello TIGERB !\n"))
})
// 启动一个http服务并监听8888端口 这里第二个参数可以指定handler
http.ListenAndServe(":8888", nil)
}
// 测试我们的服务
// --------------------
// 启动:bee run
// 访问: curl "http://127.0.0.1:8888/v1/demo"
// 响应结果:Hello TIGERB !
ListenAndServe — это дальнейшая инкапсуляция http.Server.В дополнение к описанному выше методу вы также можете использовать http.Server для прямого запуска службы.Для этого требуется установка обработчика, который реализует интерфейс Server.Handler. Когда придет запрос, этот обработчик будет выполненServeHTTPМетоды, как показано ниже:
package main
// 导入net/http包
import (
"net/http"
)
// DemoHandle server handle示例
type DemoHandle struct {
}
// ServeHTTP 匹配到路由后执行的方法
func (DemoHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello TIGERB !\n"))
}
func main() {
// ------------------ 使用http包的Server启动一个http服务 方式二 ------------------
// 初始化一个http.Server
server := &http.Server{}
// 初始化handler并赋值给server.Handler
server.Handler = DemoHandle{}
// 绑定地址
server.Addr = ":8888"
// 启动一个http服务
server.ListenAndServe()
}
// 测试我们的服务
// --------------------
// 启动:bee run
// 访问: curl "http://127.0.0.1:8888/v1/demo"
// 响应结果:Hello TIGERB !
анализ маршрутизации beego
Далее мы начинаем смотреть на код beego. получить доступ"http://127.0.0.1:8080/"Например, есть три ключевых момента для кода beego, а именно:
-
Старт: main.go ->
beego.Run() -
Зарегистрировать маршрутизацию: routers\router.go ->
beego.Router("/", &controllers.MainController{}) -
Контроллер: controllers\default.go ->
Get()
Давайте взглянем на подробный анализ 3 ключевых моментов:
Основная работа beego.Run()
// github.com/astaxie/beego/beego.go
func Run(params ...string) {
// 启动http服务之前的一些初始化 忽略 往下看
initBeforeHTTPRun()
// http服务的ip&port设置
if len(params) > 0 && params[0] != "" {
strs := strings.Split(params[0], ":")
if len(strs) > 0 && strs[0] != "" {
BConfig.Listen.HTTPAddr = strs[0]
}
if len(strs) > 1 && strs[1] != "" {
BConfig.Listen.HTTPPort, _ = strconv.Atoi(strs[1])
}
}
// 又一个run 往下看
BeeApp.Run()
}
// github.com/astaxie/beego/app.go
func (app *App) Run(mws ...MiddleWare) {
// ... 省略
// 看了下这里app.Server的类型就是*http.Server 也就是说用的原生http包 且是上面“go如何启动一个http server”中的第二种方式
app.Server.Handler = app.Handlers
// ... 省略
if BConfig.Listen.EnableHTTP {
go func() {
app.Server.Addr = addr
logs.Info("http server Running on http://%s", app.Server.Addr)
// 默认配置false不强制tcp4
if BConfig.Listen.ListenTCP4 {
//...
// 忽略 默认false
} else {
// 关键点 ListenAndServe: app.Server的类型就是*http.Server 所以这里就启动了http服务
if err := app.Server.ListenAndServe(); err != nil {
logs.Critical("ListenAndServe: ", err)
time.Sleep(100 * time.Microsecond)
endRunning <- true
}
}
}()
}
// 阻塞到服务启动
<-endRunning
}
// 看到这里http已经启动了 而且是注册Handler的方式
Затем перейдите к методу ServeHTTP этого обработчика через приведенный выше код.app.Server.Handler = app.Handlers, мы нашли следующее определение, Handler — этоControllerRegisterЗначение , поэтому каждый раз, когда приходит pro-запрос, он будет выполнятьсяControllerRegister.ServeHTTP(rw http.ResponseWriter, r *http.Request).
// src/github.com/astaxie/beego/app.go
func init() {
// 调用 创建beego框架实例的方法
BeeApp = NewApp()
}
// App结构体
type App struct {
// 关键的请求回调Handler
Handlers *ControllerRegister
// http包的服务
Server *http.Server
}
func NewApp() *App {
// 初始化http handler
cr := NewControllerRegister()
// 创建beego 实例
app := &App{Handlers: cr, Server: &http.Server{}}
return app
}
Чейз через насbeego.Run()Код, пока мы получаем вывод:
- Службы начали использовать пакет http
- не использовал
http.HandleFun()Определение стратегии маршрутизации, но способ регистрации Handler
Итак, Биего прошелbeego.Router()Управляйте роутингом сами, если придет http запрос, перезвонитеControllerRegister.ServeHTTP(rw http.ResponseWriter, r *http.Request)метод, вControllerRegister.ServeHTTP(rw http.ResponseWriter, r *http.Request)метод для сопоставления маршрута и выполнения соответствующего контроллера, который является beegoControllerInterfaceТипы методов контроллера, такие как RESTFUL или custom и т. д.
Как beego.Router() регистрирует маршруты
Прежде всего то, как загружается файл маршрутизации, мы нашли вmain.goПакет маршрутизации импортируется в файл:
package main
import (
// 导入routers包 只执行init方法
_ "beego-code-read/routers"
"github.com/astaxie/beego"
)
func main() {
beego.Run()
}
Выше мы запустили службу http, а затем ключbeego.Router()Как прописать маршрутизацию. Преследуйте код следующим образом:
beego.Router()
-> BeeApp.Handlers.Add(rootpath, c, mappingMethods...)
-> ControllerRegister.addWithMethodParams(pattern, c, nil, mappingMethods...)
-> ControllerRegister.addToRouter(method, pattern string, r *ControllerInfo)
-> *Tree.AddRouter(pattern string, runObject interface{})
Последний шаг*Tree.AddRouter()После завершения регистрации роутинга логика кода здесь пока читаться не будет.Пока процесс beego framework выпрямлен.Наконец подытожим весь процесс следующим образом:
Примечание: пакет go import эквивалентен процессу стекирования, сначала импортируйте, а затем выполните init.