1
resposta

[Projeto] Estado atual do projeto - Web Service & PostgreSQL

So fazendo essa publicacao para mostrar como esta ficando o projeto que estou fazendo com o curso, e dizer que estou gostando, aprendi bastante coisa ate. Tomei conhecimento de coisas como connections com DataBase em Go, aprendi sobre sistema de .env variavies de ambiente, e algo muito bom, pois assim evita de eu por coisas sensiveis como nomes e senhas de bancos no projeto em si, ele fica salvo num arquivo externo do projeto e isso tambem da mais modularidade e praticidade na hora de estabelecer connections, pois da para mudar tudo sem precisa ter de recopilar o projeto inteiro.

Assim esta o codigo ate entao:

Main

package main

import (
    "github.com/rickmvi/web-service/internal/product"
    "net/http"
)

func main() {
    http.HandleFunc("/", product.HandleProducts)

    if err := http.ListenAndServe(":3000", nil); err != nil {
        panic(err)
    }
}

Product

package product

import (
    "github.com/rickmvi/web-service/internal/database/postgresql"
    "html/template"
    "net/http"
)

var (
    Template = template.Must(template.ParseGlob("./static/*.html"))
)

type Product struct {
    Id          int
    Name        string
    Description string
    Price       float64
    Quantity    int
}

// HandleProducts handles HTTP requests to the root route, retrieves products from the database, and renders the handleProducts.html template.
func HandleProducts(w http.ResponseWriter, r *http.Request) {
    db := postgresql.Connection()

    getProducts, err := db.Query("select * from products")

    checkError(err)

    p := Product{}
    var products []Product

    for getProducts.Next() {
        id, quantity, name, description, price := productField()

        err = getProducts.Scan(&id, &name, &description, &price, &quantity)
        checkError(err)

        populateProduct(&p, id, name, description, price, quantity)

        products = append(products, p)
    }

    if err := Template.ExecuteTemplate(w, "index.html", products); err != nil {
        panic(err)
    }
    postgresql.Close(db)
}

// populateProduct populates a Product struct by assigning provided values for id, name, description, price, and quantity.
func populateProduct(p *Product, id *int, name *string, description *string, price *float64, quantity *int) {
    p.Id = *id
    p.Name = *name
    p.Description = *description
    p.Price = *price
    p.Quantity = *quantity
}

// productField initializes and returns pointers to product fields: id, quantity, name, description, and price.
func productField() (*int, *int, *string, *string, *float64) {
    var id, quantity int
    var name, description string
    var price float64
    return &id, &quantity, &name, &description, &price
}

// checkError checks if the provided error is non-nil and triggers a panic if it is.
func checkError(err error) {
    if err != nil {
        panic(err)
    }
}

Database/Postgreslq

package postgresql

import (
    "database/sql"
    "fmt"
    "os"

    "github.com/joho/godotenv"
    _ "github.com/lib/pq"
)

// init initializes the environment by loading variables from a .env file and checks for any loading errors.
func init() {
    err := godotenv.Load()
    checkError(err)
}

// checkError verifies if an error exists and panics if it is not nil. Use it to handle unexpected errors gracefully.
func checkError(err any) {
    if err != nil {
        panic(err)
    }
}

// Connection establishes a connection to a PostgreSQL database using environment variables and returns a *sql.DB instance.
// It panics if required environment variables are missing or if the connection fails.
func Connection() *sql.DB {
    host := os.Getenv("DB_HOST")
    port := os.Getenv("DB_PORT")
    user := os.Getenv("DB_USER")
    password := os.Getenv("DB_PASSWORD")
    dbname := os.Getenv("DB_NAME")
    sslmode := os.Getenv("DB_SSLMODE")

    if user == "" || password == "" || dbname == "" {
        panic("Missing environment variables")
    }

    conn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s", host, port, user, password, dbname, sslmode)
    db, err := sql.Open("postgres", conn)
    checkError(err)

    err = db.Ping()
    if err != nil {
        panic(fmt.Sprintf("Unable to connect to the database: %s", err))
    }

    fmt.Println("Connection with PostgreSQL established successfully")
    return db
}

// Close safely terminates the connection to the database, ensuring any errors during closure are handled appropriately.
func Close(db *sql.DB) {
    defer func(db *sql.DB) {
        err := db.Close()
        checkError(err)
    }(db)

    err := db.Close()
    if err != nil {
        panic(fmt.Sprintf("Unable to close the database connection: %s", err))
    }
}

Estrutura do Projeto
Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Matricule-se agora e aproveite até 50% OFF

O maior desconto do ano para você evoluir com a maior escola de tecnologia

QUERO APROVEITAR
1 resposta

Oi, Rick! Como vai?

Gostei muito de ver como você estruturou o projeto e aplicou boas práticas com as variáveis de ambiente para proteger dados sensíveis. Essa atenção à modularidade e à organização do código mostra que você está absorvendo bem os conceitos do curso.

Continue avançando com esse projeto.

Alura Conte com o apoio da comunidade Alura na sua jornada. Abraços e bons estudos!