likes
comments
collection
share

一个使用 GO Lang 和 PostgreSQL 的 Rest API案例

作者站长头像
站长
· 阅读数 9

Golang 是 google 开发的语言,速度极快,效率极高。由于其巨大的性能和可扩展性。是大型网站开发项目的理想选择

它是一种编译语言。编译器将代码编译为可执行文件,然后可以在任何计算机或服务器上运行

在本文中,我们将使用 GO 编程语言创建 REST API 并将 PostgreSQL 数据库添加到其中。

第 1 步:先决条件

在这篇文章中,我们将在 GO lang 中创建一个 REST API 服务器,并使用一个 PostgreSQL 数据库。

我们将创建一个数据库和 API,用于接收和存储专辑数据,例如标题、艺术家姓名和价格

这将是一个用于学习目的的简单应用程序

要阅读本文,您需要了解

  1. GO lang
  2. REST API
  3. PostgreSQL

第二步:导入依赖

在go中初始化一个新项目并创建一个文件名main.go

然后在你的代码编辑器中打开这个文件并在那里写下下面的代码

package main

import (
    "database/sql"
    "log"
    "net/http"

    "github.com/gin-gonic/gin"
    _ "github.com/lib/pq"
)

在这里我们导入了包 main 之后我们导入了像这样的包

database/sql log和 net/http 形成了 go 标准库,我们还导入了 gin 库,这是我们将在我们的应用程序中使用的 web 框架

我们正在导入Golang 的pqPostgres

_ 表示pq我们要执行包初始化函数。

func main() {

    var err error
    db, err = sql.Open("postgres", "postgres://postgres:postgres@localhost/mydb?sslmode=disable")
    if err != nil {
        log.Fatal(err)
    }
  1. id
  2. title
  3. artist
  4. price 您可以使用以下代码来初始化服务器
create database mydb

CREATE TABLE albums (
    id SERIAL PRIMARY KEY,
    title VARCHAR(255),
    artist VARCHAR(255),
    price DECIMAL(10, 2)
    );

postgres=# \c mydb
You are now connected to database "mydb" as user "postgres".

您可以使用以下代码检查表是否已创建

mydb=# select * from albums

//it returns
 id | title | artist | price
----+-------+--------+-------
(0 rows)

第 4 步:创建路由并启动服务器

现在我们已经建立了与 SQL 服务器的连接,是时候启动我们的 go 服务器了

将以下代码粘贴到连接到数据库的代码下方的主要功能中,例如

func main() {

    var err error
    db, err = sql.Open("postgres", "postgres://postgres:postgres@localhost/mydb?sslmode=disable")
    if err != nil {
        log.Fatal(err)
    }

    router := gin.Default()
    router.GET("/albums", getAlbums)
    router.POST("/albums", createAlbum)

    router.Run("localhost:8080")
}

在这里我们启动了 gin 网络服务,我们创建了两条路线,一条是 GET,另一条是 POST

当请求到达这些路由时,将调用 getAlbums 和 createAlbum 函数

我们正在运行服务器localhost://8080

第 5 步:创建 getAlbums 函数

getAlbums当 /albums 端点收到 GET 请求时将调用该函数

getAlbums 将检索数据库中存在的所有专辑列表的数据,并将其作为对 GET 请求的响应发送

创建getAlbums函数如下

func getAlbums(c *gin.Context) {
    c.Header("Content-Type", "application/json")

    rows, err := db.Query("SELECT id, title, artist, price FROM albums")
    if err != nil {
        log.Fatal(err)
    }
    defer rows.Close()

    var albums []album
    for rows.Next() {
        var a album
        err := rows.Scan(&a.ID, &a.Title, &a.Artist, &a.Price)
        if err != nil {
            log.Fatal(err)
        }
        albums = append(albums, a)
    }
    err = rows.Err()
    if err != nil {
        log.Fatal(err)
    }

    c.IndentedJSON(http.StatusOK, albums)
}

我们在这里做什么

(c *gin.Context)参数为我们的函数提供了 req 和 res 对象,并c.Header("Content-Type", "application/json")指定响应将采用 JSON 格式

rows, err := db.Query("SELECT id, title, artist, price FROM albums")
if err != nil {
log.Fatal(err)
}
defer rows.Close()

在这里,我们向数据库服务器发送一个 SQL 查询以获取相册表的所有行并返回 rows 变量中的行

如果有任何错误,也将错误记录到控制台

var albums []album
    for rows.Next() {
        var a album
        err := rows.Scan(&a.ID, &a.Title, &a.Artist, &a.Price)
        if err != nil {
            log.Fatal(err)
        }
        albums = append(albums, a)
    }
    err = rows.Err()
    if err != nil {
        log.Fatal(err)
    }

    c.IndentedJSON(http.StatusOK, albums)

接下来,我们创建一个名为 albums 的变量并将其初始化为 album 类型的数组

接下来,我们创建一个 for 循环并在数据库服务器返回的数据上运行它

我们正在迭代每一行并将其附加到相册数组。

如果有任何错误,我们会将错误记录到控制台

我们正在将相册数组转换为 JSON 格式并在 HTTP 响应中返回它。

现在我们已经启动了服务器,创建了路由,连接到数据库服务器并初始化了数据库和表,我们还有一个从服务器检索数据的函数

现在让我们真实地试用 API。我已经在服务器中放入了一些演示数据,我们可以尝试检索这些数据

(您也可以尝试用假数据填充数据库表 albums,该 API 将返回这些数据)

如果您不想在数据库中手动填充数据,请不要担心,接下来我们将创建将在 postgreSQL 数据库中填充数据的 createAlbums 函数

如果我们转到http://localhost:8080/albums url 我们可以看到服务器返回的 JSON 格式的数据

[    {        "id": "1",        "title": "Blue Train",        "artist": "John Coltrane",        "price": 56.99    }]

到目前为止,我们已经创建了很多代码

  1. 我们已经导入了所有依赖项
  2. 我们已经连接到数据库服务器
  3. 我们已经创建了路由并启动了服务器
  4. 我们已经从服务器检索数据

这是我们到目前为止编写的代码

package main

import (
    "database/sql"
    "log"
    "net/http"

    "github.com/gin-gonic/gin"
    _ "github.com/lib/pq"
)

var db *sql.DB

func main() {

    var err error
    db, err = sql.Open("postgres",         "postgres://postgres:postgres@localhost/mydb?sslmode=disable")
    if err != nil {
        log.Fatal(err)
    }

    router := gin.Default()
    router.GET("/albums", getAlbums)
    router.POST("/albums", createAlbum)

    router.Run("localhost:8080")
}

//returns a list of albums from the database
func getAlbums(c *gin.Context) {
    c.Header("Content-Type", "application/json")

    rows, err := db.Query("SELECT id, title, artist, price FROM albums")
    if err != nil {
        log.Fatal(err)
    }
    defer rows.Close()

    var albums []album
    for rows.Next() {
        var a album
        err := rows.Scan(&a.ID, &a.Title, &a.Artist, &a.Price)
        if err != nil {
            log.Fatal(err)
        }
        albums = append(albums, a)
    }
    err = rows.Err()
    if err != nil {
        log.Fatal(err)
    }

    c.IndentedJSON(http.StatusOK, albums)
}

第 6 步:创建 createAlbum 函数

现在让我们创建 createAlbum 函数,当 HTTP POST 请求到达相册端点时将调用此函数

createAlbum 函数将从 HTTP req.body 获取数据并将该数据保存在 postgreSQL 数据库中

在 getAlbums 函数后粘贴以下代码

type album struct {
    ID     string  `json:"id"`
    Title  string  `json:"title"`
    Artist string  `json:"artist"`
    Price  float64 `json:"price"`
}

func createAlbum(c *gin.Context) {

    var awesomeAlbum album
    if err := c.BindJSON(&awesomeAlbum); err != nil {
        c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid request payload"})
        return
    }

    stmt, err := db.Prepare("INSERT INTO albums (id, title, artist, price) VALUES ($1, $2, $3, $4)")
    if err != nil {
        log.Fatal(err)
    }
    defer stmt.Close()

    if _, err := stmt.Exec(awesomeAlbum.ID, awesomeAlbum.Title, awesomeAlbum.Artist, awesomeAlbum.Price); err != nil {
        log.Fatal(err)
    }

    c.JSON(http.StatusCreated, awesomeAlbum)
}

首先,我们声明一个名为 album 的 awesomeAlbum 结构。这个结构体在暂时存储 API 接收到的 HTTP 数据时会派上用场,用于检查 payload 数据是否有效

接下来在 createAlbum 函数中,我们创建一个名为 awesomeAlbum 的 var 并将其分配给 struct album 的类型

接下来我们尝试将有效负载解析为 JSON 并将数据绑定到 awessomeAlbum 结构。如果成功,我们继续下一个代码,否则我们返回错误请求负载无效

接下来我们将数据发送到 SQL 服务器并返回我们成功,否则我们将错误记录到控制台

这是完整代码的样子

package main

import (
    "database/sql"
    "log"
    "net/http"

    "github.com/gin-gonic/gin"
    _ "github.com/lib/pq"
)


type album struct {
    ID     string  `json:"id"`
    Title  string  `json:"title"`
    Artist string  `json:"artist"`
    Price  float64 `json:"price"`
}

var db *sql.DB

func main() {

    var err error
    db, err = sql.Open("postgres", "postgres://postgres:postgres@localhost/mydb?sslmode=disable")
    if err != nil {
        log.Fatal(err)
    }

    router := gin.Default()
    router.GET("/albums", getAlbums)
    router.POST("/albums", createAlbum)

    router.Run("localhost:8080")
}


func getAlbums(c *gin.Context) {
    c.Header("Content-Type", "application/json")

    rows, err := db.Query("SELECT id, title, artist, price FROM albums")
    if err != nil {
        log.Fatal(err)
    }
    defer rows.Close()

    var albums []album
    for rows.Next() {
        var a album
        err := rows.Scan(&a.ID, &a.Title, &a.Artist, &a.Price)
        if err != nil {
            log.Fatal(err)
        }
        albums = append(albums, a)
    }
    err = rows.Err()
    if err != nil {
        log.Fatal(err)
    }

    c.IndentedJSON(http.StatusOK, albums)
}


type album struct {
    ID     string  `json:"id"`
    Title  string  `json:"title"`
    Artist string  `json:"artist"`
    Price  float64 `json:"price"`
}


func createAlbum(c *gin.Context) {

    var awesomeAlbum album
    if err := c.BindJSON(&awesomeAlbum); err != nil {
        c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid request payload"})
        return
    }

    stmt, err := db.Prepare("INSERT INTO albums (id, title, artist, price) VALUES ($1, $2, $3, $4)")
    if err != nil {
        log.Fatal(err)
    }
    defer stmt.Close()

    if _, err := stmt.Exec(awesomeAlbum.ID, awesomeAlbum.Title, awesomeAlbum.Artist, awesomeAlbum.Price); err != nil {
        log.Fatal(err)
    }

    c.JSON(http.StatusCreated, awesomeAlbum)
}

结论

在本文中,我们学习了如何使用 rest API 创建一个 go 服务器,以及如何从 PostgreSQL 数据库服务器保存和检索数据

我希望你喜欢这篇文章并对你有所帮助

转载自:https://juejin.cn/post/7245812754027675704
评论
请登录