Creating a CRUD API with Golang
Here’s a complete article for creating a CRUD API with Golang, formatted in Markdown with code blocks specifying folder paths.
Introduction
This guide walks you through building a simple CRUD (Create, Read, Update, Delete) API using Golang with the Gin framework and GORM for database interaction.
Project Structure
Here’s the folder structure for our project:
crud-api/ │ ├── cmd/ │ └── server/main.go │ ├── config/ │ └── config.go │ ├── models/ │ └── book.go │ ├── routes/ │ └── routes.go │ └── database/ └── database.go
## Step 1: Initialize the Project
First, create a new Go module and install the necessary dependencies.
```bash
go mod init crud-api
go get -u github.com/gin-gonic/gin
go get -u gorm.io/gorm
go get -u gorm.io/driver/sqlite
Step 2: Database Setup
database/database.go
:
Set up the database connection and migrations using GORM.
package database
import (
"log"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
var DB *gorm.DB
func ConnectDatabase() {
var err error
DB, err = gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
log.Fatal("Failed to connect to database!", err)
}
}
Step 3: Define the Model
models/book.go
:
Define the Book
model for storing data.
package models
import "gorm.io/gorm"
type Book struct {
gorm.Model
Title string `json:"title"`
Author string `json:"author"`
Price float64 `json:"price"`
}
Step 4: Create the Routes
routes/routes.go
:
Define all the routes for CRUD operations.
package routes
import (
"github.com/gin-gonic/gin"
"crud-api/models"
"crud-api/database"
"net/http"
)
func SetupRoutes(router *gin.Engine) {
router.GET("/books", getBooks)
router.POST("/books", createBook)
router.GET("/books/:id", getBook)
router.PUT("/books/:id", updateBook)
router.DELETE("/books/:id", deleteBook)
}
func getBooks(c *gin.Context) {
var books []models.Book
database.DB.Find(&books)
c.JSON(http.StatusOK, books)
}
func createBook(c *gin.Context) {
var book models.Book
if err := c.ShouldBindJSON(&book); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
database.DB.Create(&book)
c.JSON(http.StatusOK, book)
}
func getBook(c *gin.Context) {
var book models.Book
id := c.Param("id")
if err := database.DB.First(&book, id).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Book not found!"})
return
}
c.JSON(http.StatusOK, book)
}
func updateBook(c *gin.Context) {
var book models.Book
id := c.Param("id")
if err := database.DB.First(&book, id).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Book not found!"})
return
}
if err := c.ShouldBindJSON(&book); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
database.DB.Save(&book)
c.JSON(http.StatusOK, book)
}
func deleteBook(c *gin.Context) {
var book models.Book
id := c.Param("id")
if err := database.DB.Delete(&book, id).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Book not found!"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Book deleted successfully!"})
}
Step 5: Configure the Server
cmd/server/main.go
:
Initialize the server, connect to the database, and register the routes.
package main
import (
"github.com/gin-gonic/gin"
"crud-api/database"
"crud-api/models"
"crud-api/routes"
)
func main() {
// Initialize database
database.ConnectDatabase()
database.DB.AutoMigrate(&models.Book{})
// Set up Gin
router := gin.Default()
// Register routes
routes.SetupRoutes(router)
// Run the server
router.Run(":8080")
}
Running the API
Sample Endpoints
- Create a Book:
POST /books Content-Type: application/json { "title": "Golang 101", "author": "John Doe", "price": 29.99 }
- Get All Books:
GET /books
- Get a Single Book:
GET /books/:id
- Update a Book:
PUT /books/:id Content-Type: application/json { "title": "Golang for Experts", "author": "Jane Doe", "price": 39.99 }
- Delete a Book:
DELETE /books/:id
Conclusion
Category | Type | Description | Example |
---|---|---|---|
Basic | `int` | Integer numbers. Size depends on the architecture (32 or 64 bits). | `42` |
Basic | `float64` | Double-precision floating-point numbers. | `3.14159` |
Basic | `string` | A sequence of characters. Immutable in Go. | `"Hello, Go!"` |
Basic | `bool` | Boolean values. Either `true` or `false`. | `true` |
Composite | `array` | Fixed-size, ordered collection of elements of the same type. | `[3]int{1, 2, 3}` |
Composite | `slice` | Dynamic-size version of an array. | `[]int{1, 2, 3}` |
Composite | `map` | Key-value pairs. | `map[string]int` |
Composite | `struct` | Custom composite data type. Groups fields with different types. | `type Point struct` |
Reference | `pointer` | Stores memory addresses of variables. | `*int` |
Interface | `interface{}` | Represents zero or more method signatures. Can hold any value. | `var x interface{}` |
Function | `func` | A first-class function type in Go. | `func(x int) int` |
You now have a fully functional CRUD API built with Golang, Gin, and GORM. You can expand this project by adding authentication, validation, or more complex relationships in the database.