发布于 2026-01-06 1 阅读
0

使用 Go、Gin、MySQL 和 Docker 构建博客项目 - 第一部分

使用 Go、Gin、MySQL 和 Docker 构建博客项目 - 第一部分

内容

目标受众

本系列教程不侧重于 Go 语言的基础知识,而是着重讲解如何构建后端服务。对使用 Gin 框架进行 Web 开发感兴趣的人士是理想的学习对象。

学习目标

本系列教程将教你使用 Go 构建 REST API 的基础知识。完成本系列教程后,你将掌握以下技能:

  • 配置 Golang、MySQL 和 Docker 以进行本地开发
  • 用于 CRUD API 的 Gin 框架。
  • 领域驱动开发
  • 使用 Go 进行依赖注入
  • 使用 Firebase 等进行身份验证

要求

  • Go 已安装(版本:go1.16.3 linux/amd64)
  • Docker(版本 20.10.6)和 Docker-compose(版本 1.29.1)。
  • 最好是Linux机器(因为我会使用Linux系统,但任何系统都可以)。
  • 对RESTful服务/API的总体理解。

以上版本已安装在我的机器上。您可以在此仓库
中找到该系列的完整源代码,欢迎 fork:

入门

首先,blog在您选择的位置创建一个文件夹。然后,使用以下命令在该文件夹内初始化一个新的Go 模块。blog

go mod init blog
Enter fullscreen mode Exit fullscreen mode

上述命令会创建一个go.mod文件,用于管理项目依赖项。我们来添加一些依赖项。

go get github.com/gin-gonic/gin
Enter fullscreen mode Exit fullscreen mode

上述命令将安装Gin FrameworkGorm,并创建go.sum一个文件。该文件存储有关依赖项及其版本的信息。

Gin是一个轻量级、文档齐全且速度极快的 HTTP Web 框架。其创建者声称 Gin 比其他类似框架快 40 倍。

起床 你好世界服务器

在根目录下创建一个main.go文件;打开你喜欢的编辑器,并输入以下代码

package main

import (
  "net/http"
  "github.com/gin-gonic/gin"
)

func main() {
  router := gin.Default() //new gin router initialization
  router.GET("/", func(context *gin.Context) {
    context.JSON(http.StatusOK, gin.H{"data": "Hello World !"})    
  }) // first endpoint returns Hello World
  router.Run(":8000") //running application, Default port is 8080
}
Enter fullscreen mode Exit fullscreen mode

让我们一起来看一下代码。main.go

  • package main:每个 Go 文件都是一个包。main 包始终是 Gin 项目的入口点。

  • **导入**:导入项目依赖项。

  • ** main 函数 **:每次运行应用程序时都会触发 main 函数。在函数内部,Gin router会初始化一个新的变量。同时,会在路由器上设置router一个新的端点。 *设置路由/端点需要两件事:*/

    • 端点:它是获取数据的路径。例如,如果访问者想要获取所有帖子,他们将获取该/posts端点。
    • 处理程序:它决定了如何向端点提供数据。业务逻辑包括从数据库获取/保存数据、验证用户输入等等。上下文对象的 JSON 方法用于以 JSON 格式发送数据。此方法接受 HTTP状态码和 JSON 响应作为参数。

使用以下命令启动服务器。

go run main.go
Enter fullscreen mode Exit fullscreen mode

如果看到类似以下的输出,则表示一切就绪。

[GIN-debug] GET    /                         --> main.main.func1 (3 handlers)
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8000
Enter fullscreen mode Exit fullscreen mode

在浏览器中访问http://localhost:8000/。{"data":"Hello World !"}你应该会看到。

设置 Docker

上述服务器运行方式是 Go 语言的默认应用运行方式。接下来,我们通过 Docker 的方式来配置它。在项目根目录
创建一个文件,并添加以下代码。Dockerfile

FROM golang:alpine

RUN mkdir /app

WORKDIR /app

ADD go.mod .
ADD go.sum .

RUN go mod download
ADD . .

RUN go get github.com/githubnemo/CompileDaemon

EXPOSE 8000

ENTRYPOINT CompileDaemon --build="go build main.go" --command=./main

Enter fullscreen mode Exit fullscreen mode

要构建上述 Docker 容器,Dockerfile请使用以下命令

docker build -t hello_world :1.0 .
Enter fullscreen mode Exit fullscreen mode

docker ps -a您可以在终端上查看集装箱列表。您应该可以看到带有其他信息的集装箱。

CONTAINER ID   IMAGE                    COMMAND                  CREATED          STATUS                      PORTS     NAMES
62cddf7c2659   hello_world:1.0      "/bin/sh -c 'Compile…"   23 minutes ago   Exited (0) 23 minutes ago             gifted_kilby
Enter fullscreen mode Exit fullscreen mode

要启动容器,请使用以下命令

docker run -p 8000:8000 hello_world:1.0
Enter fullscreen mode Exit fullscreen mode

在浏览器中访问http://localhost:8000/。{"data":"Hello World !"}你应该会看到。

让我们回顾一下上面 Dockerfile 中提到的 Docker 命令:

  • FROM:FROM 指的是容器使用的基础镜像。golang:1.16 镜像是一个基于 Linux 的镜像,其中安装了 golang,但没有其他额外的程序或软件。

  • WORKDIR:WORKDIR 参数用于更改工作目录。在本例中,它更改为 /app。此参数为后续命令设置工作目录。

  • ADD指令的作用是将文件从一个位置复制到另一个位置。ADD [SOURCE] [DESTINATION]这是该命令的语法。类似地,也有 COPY 命令用于相同的目的。这里,我们首先复制 go.sum 和 go.mod 文件,以便在复制所有文件之前安装所有库。

  • RUN:RUN 指令会在当前镜像之上创建一个新层,并执行所有命令,然后提交结果。提交后的镜像将用于 Dockerfile 中的下一步操作。

  • EXPOSE:EXPOSE 指示在 Docker 容器上运行的服务可通过端口 8000 访问。

  • 入口点 (Entrypoint):入口点会在从镜像创建容器后,在容器内部运行命令。一个容器中只能有一个入口点指令Dockerfile。如果使用了多个入口点指令,则会执行最后一个。在这里,容器创建完成后,入口点命令将运行我们的 Go 语言项目。

设置数据库

需要安装 MySQL 软件包才能将数据库与应用程序连接。请使用以下命令进行安装。

go get gorm.io/driver/mysql gorm.io/gorm
Enter fullscreen mode Exit fullscreen mode

Gorm是一个非常棒的 Golang ORM 库。
由于连接数据库是应用程序构建的关键部分,我们来创建一个文件夹infrastructure,并db.go在其中创建一个文件infrastructure。让我们往里面写一些内容db.go

package infrastructure

import (
    "fmt"
    "os"
    "time"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

//Database struct
type Database struct {
    DB *gorm.DB
}

//NewDatabase : intializes and returns mysql db
func NewDatabase() Database {
    USER := os.Getenv("DB_USER")
    PASS := os.Getenv("DB_PASSWORD")
    HOST := os.Getenv("DB_HOST")
    DBNAME := os.Getenv("DB_NAME")

    URL := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True&loc=Local", USER, PASS, 
    HOST, DBNAME)
    fmt.Println(URL)
    db, err := gorm.Open(mysql.Open(URL))

    if err != nil {
        panic("Failed to connect to database!")

    }
    fmt.Println("Database connection established")
    return Database{
        DB: db,
    }

}
Enter fullscreen mode Exit fullscreen mode

函数内部NewDatabase正在执行以下工作:

  1. 数据库凭据 USER、PASS、HOST 和 DBNAME 是从环境变量中获取的。
  2. 数据库 URL 是利用环境变量构建并保存到URL变量中的。
  3. 使用以下方法mysql打开一个新连接gorm.OpenURL
  4. 最后,返回数据库结构体,其中包含 gorm 数据库实例作为参数,该实例稍后将在应用程序中用于访问数据库。

环境变量

项目中有两种类型的变量program variablesenvironment variables程序变量是普通变量,用于存储代码块或模块内的值;而环境变量则在整个项目中全局可用。

设置环境变量

环境变量可以通过多种方式设置。这里,我们将使用.env文件来设置它们。.env在项目根目录下创建一个文件,并添加以下变量。

MYSQL_ROOT_PASSWORD=root
DB_USER=user
DB_PASSWORD=Password@123
DB_HOST=db
DB_PORT=3306
DB_NAME=golang
SERVER_PORT=8000
ENVIRONMENT=local
Enter fullscreen mode Exit fullscreen mode

阅读环境变量

现在,我们来编写读取文件的代码。在文件夹中.env创建一个文件,并将以下代码填充到该文件中。env.goinfrastructure

package infrastructure

import (
    "log"
    "github.com/joho/godotenv"
)

//LoadEnv loads environment variables from .env file
func LoadEnv() {
    err := godotenv.Load(".env")
    if err != nil {
        log.Fatalf("unable to load .env file")
    }
}

Enter fullscreen mode Exit fullscreen mode

使用以下命令安装 godotenv 软件包

go get github.com/joho/godotenv
Enter fullscreen mode Exit fullscreen mode

*为了加载.env文件和数据库,我们需要main.go按如下方式进行编辑 *

func main() {

    router := gin.Default()

    router.GET("/", func(context *gin.Context) {
        infrastructure.LoadEnv()  //loading env
        infrastructure.NewDatabase() //new database connection
        context.JSON(http.StatusOK, gin.H{"data": "Hello World !"})
    })
    router.Run(":8000")
}

Enter fullscreen mode Exit fullscreen mode

Docker Compose 文件

我们需要使用 Docker Compose 来定义和运行多容器 Docker 应用程序。在本例中,这些应用程序包括数据库和 Gin 应用程序。请docker-compose.yml在项目级别创建一个文件,并填充以下代码。

version: '3'
services:
  db:
    image: mysql/mysql-server:5.7
    ports:
      - "3305:3306"
    environment:
      - "MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}"
      - "MYSQL_USER=${DB_USER}"
      - "MYSQL_PASSWORD=${DB_PASSWORD}"
      - "MYSQL_DATABASE=${DB_NAME}"   
  web:
    build: .
    ports:
      - "8000:8000"
    volumes:
      - ".:/app"
    depends_on:
      - db
    links:
      - "db:database"
Enter fullscreen mode Exit fullscreen mode

让我们回顾一下compose文件中提到的术语。

  • 版本“3”:Docker Compose 版本,最新版本为 3.7

  • 服务:服务部分定义了所有要创建的不同容器。我们有两个服务,分别是webdb

  • web:这是我们 Gin 应用服务的名称。它可以是任何名称。Docker Compose 将创建以此名称命名的容器。

  • build:此子句指定 Dockerfile 的位置。.它表示 docker-compose.yml 文件所在的当前目录,Dockerfile 用于构建镜像并从中运行容器。我们也可以在此处输入 Dockerfile 的路径。

  • ports:ports 子句用于将容器端口映射到宿主机。这里映射的是端口"8000:8000",以便我们可以通过8000宿主机的端口访问我们的服务。

  • :这里我们将代码文件目录(./app 目录)附加到容器中,这样每次文件更改时就无需重新构建镜像。这也有助于在调试模式下自动重新加载服务器。

  • 链接:链接顾名思义,就是将一个服务连接到另一个服务。在这里,我们将数据库容器连接到 Web 容器,以便我们的 Web 容器可以通过桥接网络访问数据库。(注意:涉及网络!)如果您想详细了解 Docker 中的网络,请参阅:网络容器

  • 镜像:如果我们没有 Dockerfile,并且想要直接使用已构建的镜像运行服务,我们可以使用 `image` 子句指定镜像位置。Compose 会拉取镜像并从中 fork 一个容器。在本例中,我们为数据库服务指定了 `mysql/mysql-server:5.7`。

  • 环境:任何需要在容器中设置的环境变量都可以使用“environment”子句创建。

   environment:
      - "MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}"
Enter fullscreen mode Exit fullscreen mode

${MYSQL_ROOT_PASSWORD}和其他变量均已读取.env
现在,您已准备好启动容器。使用以下命令开始构建并运行。

 docker-compose up --build
Enter fullscreen mode Exit fullscreen mode

如果你的终端显示类似以下内容,则表示服务器正在运行:

db_1   | 2021-05-24T09:18:02.841094Z 0 [Note] Event Scheduler: Loaded 0 events
db_1   | 2021-05-24T09:18:02.841370Z 0 [Note] mysqld: ready for connections.
db_1   | Version: '5.7.34'  socket: '/var/lib/mysql/mysql.sock'  port: 3306  MySQL Community Server (GPL)
web_1  | 2021/05/24 09:18:06 Running build command!
web_1  | 2021/05/24 09:18:17 Build ok.
web_1  | 2021/05/24 09:18:17 Restarting the given command.
web_1  | 2021/05/24 09:18:17 stdout: [GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
web_1  | 2021/05/24 09:18:17 stdout:
web_1  | 2021/05/24 09:18:17 stdout: [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
web_1  | 2021/05/24 09:18:17 stdout:  - using env:      export GIN_MODE=release
web_1  | 2021/05/24 09:18:17 stdout:  - using code:     gin.SetMode(gin.ReleaseMode)
web_1  | 2021/05/24 09:18:17 stdout:
web_1  | 2021/05/24 09:18:17 stdout: [GIN-debug] GET    /                         --> main.main.func1 (3 handlers)
web_1  | 2021/05/24 09:18:17 stdout: [GIN-debug] Listening and serving HTTP on :8000
Enter fullscreen mode Exit fullscreen mode

访问http://localhost:8000/并在终端中检查,Database connection established应该会打印在标准输出上。

本系列文章的资料库可以在这里找到。

包起来

本系列第一部分到此结束。
下一部分我们将继续探讨:

  • 向应用程序添加模型(结构体)
  • 采用领域驱动开发模式

请务必关注我以获取下一部分的更新信息,或者订阅我的频道,这样您就不会错过我即将发表的文章。

谢谢 !!

文章来源:https://dev.to/umschaudhary/blog-project-with-go-gin-mysql-and-docker-part-1-3cg1