<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## 編寫一個 Web 服務 > Web 網頁其實也是一個 Console 命令行,只是在 Command 中啟動了一個 gin 服務器,并將配置好的路由傳入服務器中執行而已 首先我們使用 `mix` 命令創建一個 Web 項目骨架: ~~~ mix web --name=hello ~~~ 通過前面我們對 Console 命令行程序結構的了解,我們先看一下骨架的 `manifest/commands` 目錄配置的命令: ~~~ package commands import ( "github.com/mix-go/console" "github.com/mix-go/web-skeleton/commands" ) var ( Commands []console.CommandDefinition ) func init() { Commands = append(Commands, console.CommandDefinition{ Name: "web", Usage: "\tStart the api server", Options: []console.OptionDefinition{ { Names: []string{"a", "addr"}, Usage: "\tListen to the specified address", }, { Names: []string{"d", "daemon"}, Usage: "\tRun in the background", }, }, Command: &commands.WebCommand{}, }, ) } ~~~ 從上面我們可以看到定義了一個名稱為 `api` 的命令,關聯的是 `commands.WebCommand` 結構體,然后我們打開骨架 `commands/web.go` 的源碼查看他: - WebCommand 結構體中啟動了一個 gin 服務器 - 并且設置 logrus 為服務器的日志組件 - 還捕獲信號,做了服務器的 Shutdown 處理 - 代碼中 `routes.RouteDefinitionCallbacks` 定義了全部的路由配置,只需修改這個全局變量即可擴展其他接口 - `router.LoadHTMLGlob` 提前讀取了全部視圖模板文件 - `router.Static` 設置了靜態文件的處理 ~~~ package commands import ( "context" "fmt" gin2 "github.com/gin-gonic/gin" "github.com/mix-go/console" "github.com/mix-go/console/flag" "github.com/mix-go/dotenv" "github.com/mix-go/gin" "github.com/mix-go/web-skeleton/globals" "github.com/mix-go/web-skeleton/routes" "net/http" "os" "os/signal" "strings" "syscall" "time" ) const Addr = ":8080" type WebCommand struct { } func (t *WebCommand) Main() { logger := globals.Logger() // server gin.SetMode(dotenv.Getenv("GIN_MODE").String(gin.ReleaseMode)) router := gin.New(routes.RouteDefinitionCallbacks...) srv := &http.Server{ Addr: flag.Match("a", "addr").String(Addr), Handler: router, } // signal ch := make(chan os.Signal) signal.Notify(ch, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM) go func() { <-ch logger.Info("Server shutdown") ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { globals.Logger().Errorf("Server shutdown error: %s", err) } }() // error handle router.Use(gin2.Recovery()) // logger router.Use(gin.LoggerWithFormatter(logger, func(params gin.LogFormatterParams) string { return fmt.Sprintf("%s|%s|%d|%s", params.Method, params.Path, params.StatusCode, params.ClientIP, ) })) // templates router.LoadHTMLGlob(fmt.Sprintf("%s/../templates/*", console.App.BasePath)) // static file router.Static("/static", fmt.Sprintf("%s/../public/static", console.App.BasePath)) router.StaticFile("/favicon.ico", fmt.Sprintf("%s/../public/favicon.ico", console.App.BasePath)) // run welcome() logger.Info("Server start") if err := srv.ListenAndServe(); err != nil && !strings.Contains(err.Error(), "http: Server closed") { panic(err) } } ~~~ 因為骨架中已經處理了基本的常用邏輯,所以我們無需修改這個文件,只需修改 `api.RouteDefinitionCallbacks` 定義的路由,該全局變量在 `routes/all.go` 文件中: - 我們在路由配置中增加一個 `users/add` 的路由,由于新增用戶需要登錄才可操作,因此這里增加了 `middleware.SessionMiddleware()` 中間件在前面,并且使用 `router.Any` 接收全部類型的請求。 ~~~ router.Any("users/add", middleware.SessionMiddleware(), func(ctx *gin.Context) { user := controllers.UserController{} user.Add(ctx) }, ) ~~~ 然后創建一個 `controllers.UserController` 結構體,文件路徑為 `controllers/user.go`: - 代碼中當請求為 GET 時,渲染 `user_add.tmpl` 模板并傳入參數,當為 POST 時使用 gorm 在 users 表中插入了一個新記錄。 ~~~ package controllers import ( "github.com/gin-gonic/gin" "github.com/mix-go/web-skeleton/globals" "github.com/mix-go/web-skeleton/models" "net/http" "time" ) type UserController struct { } func (t *UserController) Add(c *gin.Context) { // 網頁 if c.Request.Method == http.MethodGet { c.HTML(http.StatusOK, "user_add.tmpl", gin.H{ "title": "User add", }) c.Abort() return } db := globals.DB() if err := db.Create(&models.User{ Name: c.Request.PostFormValue("name"), CreateAt: time.Now(), }).Error; err != nil { c.String(http.StatusInternalServerError, "<html><h1>%s</h1></html>", "Add error!") c.Abort() return } c.String(http.StatusInternalServerError, "<html><h1>%s</h1></html>", "Add ok!") } ~~~ 上面的代碼中使用了 `models.User` 模型,該文件定義在 `models/users.go`: - 結構體中的備注指定了字段關聯的數據庫字段名稱,表名可自行增加前綴等 ~~~ package models import "time" type User struct { ID int `gorm:"primary_key"` Name string `gorm:"column:name"` CreateAt time.Time `gorm:"column:create_at"` } func (User) TableName() string { return "users" } ~~~ 上面使用的 `globals.DB()` 都是骨架中定義好的全局方法,方法內部是采用 `mix-go/bean` 庫的依賴注入容器獲取的全局 GORM 實例,改實例的依賴配置在 `manifest/beans/db.go` 文件中: - 文件中的依賴配置定義了使用 `gorm.Open` 實例化,`bean.SINGLETON` 定義了這個實例化后的對象是單例模式,`ConstructorArgs` 字段定義了實例化時傳入的構造參數,這里傳入的 `DATABASE_DSN` 是從環境變量中獲取的,也就是說如果我們要修改連接信息,我們還需要到 `.env` 環境配置文件中修改。 ~~~ package beans import ( "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" "github.com/mix-go/bean" "github.com/mix-go/dotenv" ) func DB() { Beans = append(Beans, bean.BeanDefinition{ Name: "db", Reflect: bean.NewReflect(gorm.Open), Scope: bean.SINGLETON, ConstructorArgs: bean.ConstructorArgs{"mysql", dotenv.Getenv("DATABASE_DSN").String()}, }, ) } ~~~ ## 編譯與測試 > 也可以在 Goland Run 里配置 Program arguments 直接編譯執行,[Goland 使用] 章節有詳細介紹 接下來我們編譯上面的程序: ~~~ // linux & macOS go build -o bin/go_build_main_go main.go // win go build -o bin/go_build_main_go.exe main.go ~~~ 首先在命令行啟動 `web` 服務器: ~~~ $ bin/go_build_main_go web ___ ______ ___ _ /__ ___ _____ ______ / __ `__ \/ /\ \/ /__ __ `/ __ \ / / / / / / / /\ \/ _ /_/ // /_/ / /_/ /_/ /_/_/ /_/\_\ \__, / \____/ /____/ Server Name: mix-web Listen Addr: :8080 System Name: darwin Go Version: 1.13.4 Framework Version: 1.0.9 time=2020-09-16 20:24:41.515 level=info msg=Server start file=web.go:58 ~~~ 瀏覽器測試 - 首先瀏覽器進入 http://127.0.0.1:8080/login 獲取 session ![](https://img.kancloud.cn/d2/28/d228229bb3dcad0fa162968254f52ce3_507x159.png) - 提交表單后跳轉到 http://127.0.0.1:8080/users/add 頁面 ![](https://img.kancloud.cn/7f/3c/7f3cdda28ef917388b698a1900d19f55_367x163.png)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看