The CRUD operations (create, read, update, delete) are the basic functionality of any web application when working with a database. This example will show you how to create the CRUD API with Go and using MySQL as a database.
Setting up the Go project dependencies.
go mod init app go get github.com/gin-gonic/gin go get gorm.io/gorm go get gorm.io/driver/mysql go get github.com/joho/godotenv
Create a testing database named "example" and run the database.sql file to import the table and data.
├─ .env ├─ main.go ├─ config │ └─ db.go ├─ controllers │ └─ product_controller.go ├─ models │ └─ product.go ├─ public │ └─ index.html └─ router └─ router.go
This file contains the database connection information.
DB_HOST=localhost DB_PORT=3306 DB_DATABASE=example DB_USER=root DB_PASSWORD=
This file sets up the database connection using GORM. It declares a global variable DB to hold the database connection instance to use later in our application.
package config import ( "fmt" "os" "github.com/joho/godotenv" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/schema" ) var DB *gorm.DB func SetupDatabase() { godotenv.Load() connection := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=true", os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_HOST"), os.Getenv("DB_PORT"), os.Getenv("DB_DATABASE")) db, _ := gorm.Open(mysql.Open(connection), &gorm.Config{NamingStrategy: schema.NamingStrategy{SingularTable: true}}) DB = db }
This file sets up routing for a Gin web application. It initializes a router, serves a static index.html file at the root URL, defines API routes for CRUD operations.
package router import ( "app/controllers" "github.com/gin-gonic/gin" ) func SetupRouter() { productController := controllers.ProductController{} router := gin.Default() router.StaticFile("/", "./public/index.html") router.Group("/api"). GET("/products", productController.Index). POST("/products", productController.Create). GET("/products/:id", productController.Get). PUT("/products/:id", productController.Update). DELETE("/products/:id", productController.Delete) router.Run() }
This file defines the Product model for the application. This model is used for database operations involving products.
package models type Product struct { Id int `gorm:"primaryKey;autoIncrement"` Name string Price float64 }
This file defines all functions required to handle incoming requests and perform any CRUD operations.
package controllers import ( "app/config" "app/models" "net/http" "strconv" "github.com/gin-gonic/gin" ) type ProductController struct { } func (con *ProductController) Index(c *gin.Context) { var products []models.Product config.DB.Find(&products) c.JSON(http.StatusOK, products) } func (con *ProductController) Get(c *gin.Context) { var product models.Product config.DB.First(&product, c.Params.ByName("id")) c.JSON(http.StatusOK, product) } func (con *ProductController) Create(c *gin.Context) { var product models.Product c.BindJSON(&product) if err := config.DB.Create(&product).Error; err != nil { c.AbortWithError(http.StatusBadRequest, err) return } c.JSON(http.StatusOK, product) } func (con *ProductController) Update(c *gin.Context) { var product models.Product c.BindJSON(&product) product.Id, _ = strconv.Atoi(c.Params.ByName("id")) if err := config.DB.Updates(&product).Error; err != nil { c.AbortWithError(http.StatusBadRequest, err) return } c.JSON(http.StatusOK, product) } func (con *ProductController) Delete(c *gin.Context) { var product models.Product if err := config.DB.Delete(&product, c.Params.ByName("id")).Error; err != nil { c.AbortWithError(http.StatusBadRequest, err) return } c.Status(http.StatusOK) }
c.BindJSON() parse the JSON payload from the request body into a Go struct.
config.DB the GORM instance that use to perform the desired database operation.
c.JSON() send a JSON response with the result of the operation and the appropriate HTTP status code.
This file is the main entry point of our application. It will create and setting up the Gin web application.
package main import ( "app/config" "app/router" ) func main() { config.SetupDatabase() router.SetupRouter() }
This file will be used to create a basic user interface for testing our API.
<!DOCTYPE html> <head> <style> li { margin-bottom: 5px; } textarea { width: 100%; } </style> </head> <body> <h1>Example CRUD</h1> <ul> <li><button onclick="getProducts()">Get Products</button></li> <li><button onclick="getProduct()">Get Product</button></li> <li><button onclick="createProduct()">Create Product</button></li> <li><button onclick="updateProduct()">Update Product</button></li> <li><button onclick="deleteProduct()">Delete Product</button></li> </ul> <textarea id="text_response" rows="20"></textarea> <script> function showResponse(res) { res.text().then(text => { let contentType = res.headers.get('content-type') if (contentType && contentType.startsWith('application/json')) { text = JSON.stringify(JSON.parse(text), null, 4) } document.getElementById('text_response').innerHTML = text }) } function getProducts() { fetch('/api/products').then(showResponse) } function getProduct() { let id = prompt('Input product id') fetch('/api/products/' + id).then(showResponse) } function createProduct() { let name = prompt('Input product name') let price = parseFloat(prompt('Input product price')) fetch('/api/products', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name, price }) }).then(showResponse) } function updateProduct() { let id = parseInt(prompt('Input product id to update')) let name = prompt('Input new product name') let price = parseFloat(prompt('Input new product price')) fetch('/api/products/' + id, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name, price }) }).then(showResponse) } function deleteProduct() { let id = prompt('Input product id to delete') fetch('/api/products/' + id, { method: 'DELETE' }).then(showResponse) } </script> </body> </html>
go run main.go
Open the web browser and goto http://localhost:8080
Click the "Get Products" button. The API will return all products data.
Click the "Get Product" button and enter "1" for the product id. The API will return a product data.
Click the "Create Product" button and enter "test-create" for the product name and "100" for the price. The API will return a newly created product.
Click the "Update Product" button and enter "101" for the product id and "test-update" for the name and "200" for the price. The API will return an updated product.
Click the "Delete Product" button and enter "101" for the product id. The API will return nothing, which is acceptable as we do not return anything from our API.
In this article, you have learned how to create and settings up the Gin framework in order to create a CRUD API. Utilize GORM as an ORM to perform the CRUD operations on the database. Test our API using JavaScript. I hope you will enjoy the article.
Source code: https://github.com/StackPuz/Example-CRUD-Go
Create a CRUD Web App: https://stackpuz.com
The above is the detailed content of Create a CRUD API with Go. For more information, please follow other related articles on the PHP Chinese website!