Back

Golang Basics Crud

Absolutely! Let's get started. Here's how we'll modify the project to add CRUD operations, user registration, and secure everything with PostgreSQL and JWT.

Prerequisites

  • Basic understanding of SQL and how to work with databases.
  • PostgreSQL installed and running on your system.

1. Set up PostgreSQL Database

  1. Create a Database: Use a tool like pgAdmin or the psql command-line tool to create a database (e.g., go_fiber_api_db).
  2. Create a User Table:
    CREATE TABLE users (
        id SERIAL PRIMARY KEY,
        username VARCHAR(50) UNIQUE NOT NULL,
        password VARCHAR(255) NOT NULL -- Store hashed password!
    );
    

2. Install PostgreSQL Driver

go get -u github.com/jackc/pgx/v4/stdlib

3. Modify Models (models/user.go)

package models

// User model representing the database table
type User struct {
    ID       int    `json:"id"`
    Username string `json:"username"`
    Password string `json:"password"` // Don't expose in API responses
}

4. Database Connection (utils/db.go)

package utils

import (
    "context"
    "fmt"
    "log"

    "github.com/jackc/pgx/v4/pgxpool"
)

var db *pgxpool.Pool // Global database connection pool

func ConnectDB() {
    // Read database credentials from environment variables
    dbURL := fmt.Sprintf("postgres://user:password@localhost:5432/go_fiber_api_db")

    var err error
    db, err = pgxpool.Connect(context.Background(), dbURL)
    if err != nil {
        log.Fatalf("Unable to connect to database: %v\n", err)
    }
}

5. Authentication Functions (controllers/auth.go)

package controllers

import (
    // ... other imports ...
    "golang.org/x/crypto/bcrypt" // For password hashing
)

// Register creates a new user
func Register(c *fiber.Ctx) error {
    var user models.User
    if err := c.BodyParser(&user); err != nil {
        return err
    }

    // Hash password
    hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
    if err != nil {
        return err
    }
    user.Password = string(hashedPassword)

    // Insert user into database
    _, err = utils.db.Exec(c.Context(), "INSERT INTO users (username, password) VALUES ($1, $2)", user.Username, user.Password)
    if err != nil {
        return c.Status(500).SendString(err.Error())
    }

    // ... Generate JWT and respond ... (similar to earlier example)
    return c.JSON(fiber.Map {"message": "User created"})
}

// Login authenticates and generates a JWT
func Login(c *fiber.Ctx) error {
    // ... Logic similar to earlier example, but fetch user
    // from the database and compare hashed passwords ...
}

6. CRUD Functions (Example - controllers/products.go)

// ... other controllers code

// CreateProduct adds a new product (requires auth)
func CreateProduct(c *fiber.Ctx) error {
    // ... Authenticate user (using middleware) ...

    var product models.Product
    if err := c.BodyParser(&product); err != nil {
        return err
    }

    // Insert product into database
    _, err = db.Exec(c.Context(), "INSERT INTO products (name, price) VALUES ($1, $2)", product.Name, product.Price)
    if err != nil {
        return c.Status(500).SendString(err.Error())
    }

    return c.JSON(fiber.Map{"message": "Product created"})
}

7. Update main.go

  • Call utils.ConnectDB() to establish the database connection.