Golang 是 google 开发的语言,速度极快,效率极高。由于其巨大的性能和可扩展性。是大型网站开发项目的理想选择
它是一种编译语言。编译器将代码编译为可执行文件,然后可以在任何计算机或服务器上运行
在本文中,我们将使用 GO 编程语言创建 REST API 并将 PostgreSQL 数据库添加到其中。
第 1 步:先决条件
在这篇文章中,我们将在 GO lang 中创建一个 REST API 服务器,并使用一个 PostgreSQL 数据库。
我们将创建一个数据库和 API,用于接收和存储专辑数据,例如标题、艺术家姓名和价格
这将是一个用于学习目的的简单应用程序
要阅读本文,您需要了解
- GO lang
- REST API
- 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 的pq
库Postgres
_ 表示pq
我们要执行包初始化函数。
func main() {
var err error
db, err = sql.Open("postgres", "postgres://postgres:postgres@localhost/mydb?sslmode=disable")
if err != nil {
log.Fatal(err)
}
- id
- title
- artist
- 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 }]
到目前为止,我们已经创建了很多代码
- 我们已经导入了所有依赖项
- 我们已经连接到数据库服务器
- 我们已经创建了路由并启动了服务器
- 我们已经从服务器检索数据
这是我们到目前为止编写的代码
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 数据库服务器保存和检索数据
我希望你喜欢这篇文章并对你有所帮助