Add initial project structure with database connection and routing setup

- Create .env.example and .gitignore to manage environment variables
- Implement database connection logic in bd.go
- Define project model and data retrieval functions in projet.go
- Set up HTTP routes for project management in routes/projet.go
- Add main entry point in main.go to start the server
This commit is contained in:
=
2025-09-23 09:35:10 +02:00
commit 4335fd5cae
8 changed files with 193 additions and 0 deletions
View File
+1
View File
@@ -0,0 +1 @@
.env
+38
View File
@@ -0,0 +1,38 @@
package bd
import (
"database/sql"
"log"
"os"
"github.com/go-sql-driver/mysql"
"github.com/joho/godotenv"
)
var db *sql.DB
func GetDB() *sql.DB {
if db == nil {
errenv := godotenv.Load()
if errenv != nil {
log.Fatal("Error loading .env file")
}
// Capture connection properties.
cfg := mysql.NewConfig()
cfg.User = os.Getenv("DB_USER")
cfg.Passwd = os.Getenv("DB_PASS")
cfg.Net = "tcp"
cfg.Addr = os.Getenv("DB_HOST")
cfg.DBName = os.Getenv("DB_NAME")
// Get a database handle.
var err error
db, err = sql.Open("mysql", cfg.FormatDSN())
if err != nil {
log.Fatal(err)
}
}
return db
}
+10
View File
@@ -0,0 +1,10 @@
module api_serveurless_go
go 1.25.1
require (
github.com/go-sql-driver/mysql v1.9.3
github.com/joho/godotenv v1.5.1
)
require filippo.io/edwards25519 v1.1.0 // indirect
+6
View File
@@ -0,0 +1,6 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
+14
View File
@@ -0,0 +1,14 @@
package main
import (
"api_serveurless_go/routes"
"net/http"
)
func main() {
// Configuration des routes
routes.SetupRoutes()
// Démarrage du serveur
http.ListenAndServe(":3000", nil)
}
+62
View File
@@ -0,0 +1,62 @@
package requette
import (
"api_serveurless_go/bd"
"database/sql"
"log"
)
type Projet struct {
Id int `json:"id"`
Name string `json:"name"`
ShortDescription string `json:"shortdescription"`
}
func GetAllProjets() []Projet {
db := bd.GetDB()
stmt, err := db.Prepare("SELECT * FROM projet")
if err != nil {
log.Fatal(err)
}
row, err := stmt.Query()
defer stmt.Close()
if err != nil {
log.Fatal(err)
}
return hydrateProjets(row)
}
func GetProjetByID(id int) Projet {
db := bd.GetDB()
stmt, err := db.Prepare("SELECT * FROM projet WHERE id = ?")
if err != nil {
log.Fatal(err)
}
row := stmt.QueryRow(id)
defer stmt.Close()
return hydrateProjet(row)
}
func hydrateProjet(row *sql.Row) Projet {
var projet Projet
err := row.Scan(&projet.Id, &projet.Name, &projet.ShortDescription)
if err != nil {
log.Fatal(err)
}
return projet
}
func hydrateProjets(rows *sql.Rows) []Projet {
var projets []Projet
for rows.Next() {
var projet Projet
err := rows.Scan(&projet.Id, &projet.Name, &projet.ShortDescription)
if err != nil {
log.Fatal(err)
}
projets = append(projets, projet)
}
return projets
}
+62
View File
@@ -0,0 +1,62 @@
package routes
import (
"api_serveurless_go/requette"
"encoding/json"
"fmt"
"net/http"
"strconv"
"strings"
)
// SetupRoutes configure toutes les routes de l'application
func SetupRoutes() {
http.HandleFunc("/", homeHandler)
http.HandleFunc("/api/projets", projetsHandler)
http.HandleFunc("/api/projet/", projetHandler)
}
// homeHandler gère la route racine
func homeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to my website!")
}
// projetsHandler gère la liste des projets
func projetsHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(requette.GetAllProjets())
case "POST":
fmt.Fprintf(w, "Créer un nouveau projet")
default:
http.Error(w, "Méthode non autorisée", http.StatusMethodNotAllowed)
}
}
// projetHandler gère les actions sur un projet spécifique
func projetHandler(w http.ResponseWriter, r *http.Request) {
id := strings.TrimPrefix(r.URL.Path, "/api/projet/")
if id == "" {
http.Error(w, "ID manquant", http.StatusBadRequest)
return
}
idInt, err := strconv.Atoi(id)
if err != nil {
http.Error(w, "ID invalide", http.StatusBadRequest)
return
}
switch r.Method {
case "GET":
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(requette.GetProjetByID(idInt))
case "PUT":
fmt.Fprintf(w, "Modifier le projet %d", idInt)
case "DELETE":
fmt.Fprintf(w, "Supprimer le projet %d", idInt)
default:
http.Error(w, "Méthode non autorisée", http.StatusMethodNotAllowed)
}
}