GOG - Practice

Mise en place GORM

go get -u gorm.io/gorm
go get -u gorm.io/driver/postgres
package main

import (
	"fmt"
	"gorm.io/driver/postgres"
	"gorm.io/gorm"
	"log"
)

var DB *gorm.DB

func initDatabase() {
	dsn := "host=localhost user=gormuser password=gormpassword dbname=gormdb port=5432 sslmode=disable TimeZone=Europe/Paris"
	var err error
	DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{})
	if err != nil {
		log.Fatal("Failed to connect to database: ", err)
	}
	fmt.Println("Database connected successfully!")
}

func main() {
	initDatabase()
}

type User struct {
	ID       uint   `gorm:"primaryKey"`
	Name     string
	Email    string  `gorm:"unique"`
	Password string
}

func migrate() {
	DB.AutoMigrate(&User{})
	fmt.Println("Database migrated!")
}


func main() {
	initDatabase()
	migrate()
}

func createUser(name string, email string, password string) {
	user := User{Name: name, Email: email, Password: password}
	DB.Create(&user)
	fmt.Printf("User %s created successfully!\n", user.Name)
}

// Dans main

createUser("John Doe", "john@example.com", "securepassword")
func getUsers() {
	var users []User
	DB.Find(&users)
	for _, user := range users {
		fmt.Printf("User: %s, Email: %s\n", user.Name, user.Email)
	}
}

func updateUserEmail(id uint, newEmail string) {
	var user User
	DB.First(&user, id)
	user.Email = newEmail
	DB.Save(&user)
	fmt.Printf("User %s updated with new email: %s\n", user.Name, user.Email)
}

// Dans main

updateUserEmail(1, "john.doe@newemail.com")

func deleteUser(id uint) {
	var user User
	DB.Delete(&user, id)
	fmt.Printf("User with ID %d deleted successfully!\n", id)
}

// Dans main
deleteUser(1)



Mise en place Golang avec Redis

# Executer redis 
docker run --name redis-cache -d -p 6379:6379 redis

# Executer redis-cli
docker exec -it redis-cache redis-cli ping

# Créer le repo
mkdir go-redis-cache
cd go-redis-cache
go mod init go-redis-cache

# Gin-Gonic
go get -u github.com/gin-gonic/gin
go get -u github.com/go-redis/redis/v8

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"context"
	"github.com/go-redis/redis/v8"
	"time"
)

var ctx = context.Background()

func main() {
	r := gin.Default()

	// Connecter Redis
	rdb := redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "", // Pas de mot de passe par défaut
		DB:       0,  // Utiliser la base de données par défaut
	})

	// Route pour obtenir une donnée
	r.GET("/data/:key", func(c *gin.Context) {
		key := c.Param("key")

		// Vérifier si la donnée est en cache
		val, err := rdb.Get(ctx, key).Result()
		if err == redis.Nil {
			// Simuler une récupération lente de la donnée depuis la base de données
			time.Sleep(2 * time.Second)
			val = fmt.Sprintf("Data for key %s", key)

			// Stocker la donnée dans Redis avec une durée d'expiration
			err := rdb.Set(ctx, key, val, 10*time.Second).Err()
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to cache data"})
				return
			}
		} else if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve data"})
			return
		}

		// Retourner la donnée (du cache ou de la "base de données")
		c.JSON(http.StatusOK, gin.H{"data": val})
	})

	// Démarrer le serveur HTTP
	r.Run(":8080")
}

Mise en place Gin-Gonic

go get -u github.com/gin-gonic/gin
package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()

	// Définir une route GET
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})

	// Démarrer le serveur sur le port 8080
	r.Run(":8080")
}
go run main.go
// Création de routes et gestion des requêtes
package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

var users = []string{"Alice", "Bob", "Charlie"}

func main() {
	r := gin.Default()

	// Route pour obtenir tous les utilisateurs
	r.GET("/users", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"users": users,
		})
	})

	// Route pour ajouter un utilisateur
	r.POST("/users", func(c *gin.Context) {
		var newUser string
		if err := c.BindJSON(&newUser); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid data"})
			return
		}
		users = append(users, newUser)
		c.JSON(http.StatusCreated, gin.H{"user": newUser})
	})

	// Démarrer le serveur
	r.Run(":8080")
}

func LoggerMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		fmt.Println("Request received: ", c.Request.Method, c.Request.URL)
		c.Next()
	}
}

func main() {
	r := gin.Default()

	// Utiliser le middleware de journalisation
	r.Use(LoggerMiddleware())

	// Définir des routes...
	r.Run(":8080")
}
r.POST("/users", func(c *gin.Context) {
	var newUser string
	if err := c.BindJSON(&newUser); err != nil || newUser == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user data"})
		return
	}
	users = append(users, newUser)
	c.JSON(http.StatusCreated, gin.H{"user": newUser})
})

r.GET("/error", func(c *gin.Context) {
	c.JSON(http.StatusInternalServerError, gin.H{"error": "Something went wrong"})
})
package main

import (
	"bytes"
	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestGetUsers(t *testing.T) {
	// Configurer Gin en mode test
	r := gin.Default()

	// Route de test
	r.GET("/users", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"users": users,
		})
	})

	// Créer une requête HTTP
	req, _ := http.NewRequest("GET", "/users", nil)
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)

	// Assertions
	assert.Equal(t, http.StatusOK, w.Code)
	assert.Contains(t, w.Body.String(), "Alice")
}

func TestPostUser(t *testing.T) {
	// Configurer Gin en mode test
	r := gin.Default()

	// Route de test
	r.POST("/users", func(c *gin.Context) {
		var newUser string
		if err := c.BindJSON(&newUser); err != nil || newUser == "" {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user data"})
			return
		}
		users = append(users, newUser)
		c.JSON(http.StatusCreated, gin.H{"user": newUser})
	})

	// Créer une requête HTTP
	user := `"David"`
	req, _ := http.NewRequest("POST", "/users", bytes.NewBufferString(user))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)

	// Assertions
	assert.Equal(t, http.StatusCreated, w.Code)
	assert.Contains(t, w.Body.String(), "David")
}
go test

Mise en place d'un service GRPC

  • Installation du packet
apt install protobuf-compiler
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
  • Construction des protos
ENV :
GO_MOD = monpacket
PROTOBUF_DIR = ./proto
---
Commands :

protoc --experimental_allow_proto3_optional \
--go_out=src --go_opt=paths=source_relative --go_opt=Mprotos_ext/lameduse-utils-image_manager-v1.proto=$(GO_MOD)/protos protos/pb.proto \
--go-grpc_out=src --go-grpc_opt=paths=source_relative --go-grpc_opt=Mprotos_ext/lameduse-utils-image_manager-v1.proto=$(GO_MOD)/protos protos/pb.proto

  • Protobuff example
syntax = "proto3";

package v1.service.core.lameduse;
option go_package = "monpacket/protos";

enum Status {
    NO_STATUS = 0; // No status / Unknow
    OK = 1; // Request is ok
    ERROR_INTERNAL = 2; // Request failed because of an internal error
    ERROR_ACCESS = 3; // Request failed because access is denied
    ERROR_EXIST = 4; // Request failed because ressource already exist
    ERROR_PARAMS = 5; // Request failed because params are incorrect
}

/// TAG Manager Service

service TagManager {
    rpc CreateTag(TagCreateRequest) returns (TagCreateResponse); // Create an new tag
    rpc ListTag(TagListRequest) returns (TagListResponse); // List existing tags with partial
}

message Tag {
    uint64 id = 1;
    string name = 2;
}

message TagCreateRequest {
    string name = 1; // Name of the tag to create
}

message TagCreateResponse {
    bool ok = 1; // if ok == true request was successful
    Status status = 2; // Return the status
}

message TagListRequest {
    string partial = 1; // Partial name of the tag
}

message TagListResponse {
    bool ok = 1; // if ok == true request was successful
    repeated string tags = 2; // Return the matching tags
}

/// Collection Manager Service

service CollectionManager {
    rpc CreateCollection(CollectionCreateRequest) returns (CollectionCreateResponse); // Create an new collection
    rpc ListCollection(CollectionListRequest) returns (CollectionListResponse); // List existing collection with partials
    rpc GetCollection(CollectionGetRequest) returns (CollectionGetResponse); // Get a collection
    rpc UpdateCollection(CollectionUpdateRequest) returns (CollectionUpdateResponse); // Update a collection
}

message CollectionObject {
    uint64 id = 1; // ID of the collection
    string name = 2; // Name of the collection
}

message CollectionCreateRequest {
    string name = 1; // Name of the collection to create
}

message CollectionCreateResponse {
    bool ok = 1; // if ok == true request was successful
    Status status = 2; // Return the status
    uint64 id = 3; // Return the collection ID
}

message CollectionListRequest {
    string partial = 1; // Partial name of the collection
}

message CollectionListResponse {
    bool ok = 1; // if ok == true request was successful
    repeated CollectionObject collections = 2; // Return the matching collection ids
}

message CollectionGetRequest {
    uint64 id = 1; // ID of the collection
}

message CollectionGetResponse {
    bool ok = 1; // if ok == true request was successful
    CollectionObject collection = 2; // Return the collection
}

message CollectionUpdateRequest {
    uint64 id = 1; // ID of the collection
    string name = 2; // Name of the collection
}

message CollectionUpdateResponse {
    bool ok = 1; // if ok == true request was successful
    Status status = 2; // Return the status
}

service CollectionItemManager {
    rpc CreateCollectionItem(CollectionItemCreateRequest) returns (CollectionItemCreateResponse); // Create an new collection
    rpc ListCollectionItem(CollectionItemListRequest) returns (CollectionItemListResponse); // List existing collection with partials
    rpc GetCollectionItem(CollectionItemGetRequest) returns (CollectionItemGetResponse); // Get a collection
    rpc UpdateCollectionItem(CollectionItemUpdateRequest) returns (CollectionItemUpdateResponse); // Update a collection
    rpc DeleteCollectionItem(CollectionItemDeleteRequest) returns (CollectionItemDeleteResponse); // Delete a collection
}

message CollectionItemObject {
    uint64 id = 1;
    string name = 2;
    uint64 image_id = 3;
    uint64 collection_id = 4;
}

message CollectionItemCreateRequest {
    CollectionItemObject item = 1;
}

message CollectionItemCreateResponse {
    bool ok = 1; // if ok == true request was successful
    Status status = 2; // Return the status
    uint64 id = 3; // Return the collection ID
}

message CollectionItemListRequest {
    uint64 collection_id = 1;
}

message CollectionItemListResponse {
    bool ok = 1; // if ok == true request was successful
    repeated CollectionItemObject items = 2; // Return the matching collection ids
    Status status = 3; // Return the status
}

message CollectionItemGetRequest {
    uint64 id = 1; // ID of the collection
}

message CollectionItemGetResponse {
    bool ok = 1; // if ok == true request was successful
    CollectionItemObject item = 2; // Return the collection
    Status status = 3; // Return the status
}

message CollectionItemUpdateRequest {
    CollectionItemObject item = 1;
}

message CollectionItemUpdateResponse {
    bool ok = 1; // if ok == true request was successful
    Status status = 2; // Return the status
}

message CollectionItemDeleteRequest {
    uint64 id = 1; // ID of the collection
}

message CollectionItemDeleteResponse {
    bool ok = 1; // if ok == true request was successful
    Status status = 2; // Return the status
}

service ImageManager {
    rpc List(ImageListRequest) returns (ImageListResponse); // Get images
}

message ImageCreateRequest {
    string name = 1;
}

message ImageCreateResponse {
    bool ok = 1; // if ok == true request was successful
    Status status = 2; // Return the status
    uint64 id = 3; // Return the image ID
}

message ImageListRequest {

}

message ImageListResponse {
    bool ok = 1; // if ok == true request was successful
    repeated string ids = 2; // Return the matching collection ids
}

service UserManager {
    rpc UserCreate(UserCreateRequest) returns (UserCreateResponse);
    rpc UserLogin(UserLoginRequest) returns (UserLoginResponse);
    rpc UserGet(UserGetRequest) returns (UserGetResponse);
    rpc UserUpdate(UserUpdateRequest) returns (UserUpdateResponse);
}

message UserObject {
    string id = 1;
    string email = 2;
    string phone = 3;
    string firstname = 4;
    string lastname = 5;
    bool email_ok = 6;
    string raw_password = 8;
    string hash_password = 9;
    string key = 10;
    bool role_admin = 11;
    bool role_factory = 12;
    bool role_customer_individual = 13;
    bool role_customer_business = 14;
    string info_address1 = 17;
    string info_address2 = 18;
    string info_city = 19;
    string info_region = 20;
    string into_city_code = 21;
    string info_contry = 22;
    string info_business_localid = 23;
    string info_business_vatid = 24;
    string info_business_name = 25;
}

message UserCreateRequest {
    string email = 2;
    string raw_password = 3;
}

message UserCreateResponse {
    bool ok = 1; // if ok == true request was successful
    Status status = 2; // Return the status
    string message = 3; // message for the request
}

message UserLoginRequest {
    string email = 2;
    string raw_password = 3;
}

message UserLoginResponse {
    bool ok = 1; // if ok == true request was successful
    Status status = 2; // Return the status
    string message = 3; // message for the request
    string token = 4; // token for the user
}

message UserGetRequest {
    string token = 2;
    bool refresh_only = 3;
}

message UserGetResponse {
    bool ok = 1; // if ok == true request was successful
    Status status = 2; // Return the status
    string message = 3; // message for the request
    UserObject user = 4; // user object
    string refresh_token = 5; // token for the user
}

message UserUpdateRequest {
    string token = 1;
    UserObject user = 2;
}

message UserUpdateResponse {
    bool ok = 1; // if ok == true request was successful
    Status status = 2; // Return the status
    string message = 3; // message for the request
}