Go: RESTful - um exemplo completo com persistência

De Aulas
Revisão de 08h56min de 2 de abril de 2024 por Admin (discussão | contribs) (→‎userdao.go)

Afluentes: Sistemas Distribuídos e Mobile

Base de Dados

Tabela users

create table users (
    id varchar(16) not null,
    name varchar(50) not null,
    email varchar(50) not null,
    primary key (id)
);

database.go

package main

import (
	"database/sql"
	"fmt"

	_ "github.com/lib/pq"
)

// Database class
type Database struct {
	connection *sql.DB
	dbtype     string
	info       string
	err        error
}

// NewDatabase Constructor
func NewDatabase(dbhost string, dbtype string, dbname string, dbuser string, dbpass string) *Database {
	db := new(Database)
	db.dbtype = dbtype
	db.info = fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable", dbuser, dbpass, dbname)
	return db
}

// Get return connection
func (db *Database) Get() *sql.DB {
	if db.connection == nil {
		db.connection, db.err = sql.Open(db.dbtype, db.info)
	}
	return db.connection
}

// Close function
func (db *Database) Close() {
	db.connection.Close()
}

user.go

package main

type User struct {
	Id    string `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
}

func NewUser(id string, name string, email string) *User {
	user := new(User)
	user.Id = id
	user.Name = name
	user.Email = email
	return user
}

userdao.go

package main

import "fmt"

type UserDAO struct {
	db    *Database
	users []*User
}

func NewUserDAO(db *Database) *UserDAO {
	userdao := new(UserDAO)
	userdao.db = db
	userdao.users = make([]*User, 0)
	return userdao
}

func (userdao *UserDAO) GetAll() []*User {
	userdao.users = make([]*User, 0)
	db := userdao.db.Get()
	rows, err := db.Query("select * from users")
	if err != nil {
		fmt.Println(err.Error())
	}
	for rows.Next() {
		var id string
		var name string
		var email string
		rows.Scan(&id, &name, &email)
		userdao.users = append(userdao.users, NewUser(id, name, email))
	}
	return userdao.users
}

func (userdao *UserDAO) Insert(user *User) {
	db := userdao.db.Get()
	query := "insert into users (id, name, email) values ($1, $2, $3)"
	_, err := db.Query(query, user.Id, user.Name, user.Email)
	if err != nil {
		fmt.Println(err.Error())
	}
}

func (userdao *UserDAO) Get(id string) *User {
	db := userdao.db.Get()
	query := "select * from users where id=$1"
	rows, err := db.Query(query, id)
	if err != nil {
		fmt.Println(err.Error())
	}
	if rows.Next() {
		var id string
		var name string
		var email string
		rows.Scan(&id, &name, &email)
		return NewUser(id, name, email)
	}
	return nil
}

func (userdao *UserDAO) Update(user *User) string {
	db := userdao.db.Get()
	query := "update users set name=$2, email=$3 where id=$1"
	_, err := db.Query(query, user.Id, user.Name, user.Email)
	if err != nil {
		fmt.Println(err.Error())
		return err.Error()
	}
	return "ok"
}

func (userdao *UserDAO) Delete(id string) string {
	db := userdao.db.Get()
	query := "delete from users where id=$1"
	_, err := db.Query(query, id)
	if err != nil {
		fmt.Println(err.Error())
		return err.Error()
	}
	return "ok"
}

main.go

package main

import (
	"encoding/json"
	"fmt"
	"net/http"
)

func main() {
	db := NewDatabase("localhost", "postgres", "distribuidos", "saulo", "1234")
	defer db.Close()
	dao := NewUserDAO(db)

	router := http.NewServeMux()

	router.HandleFunc("POST /users", func(w http.ResponseWriter, r *http.Request) {
		var user User
		err := json.NewDecoder(r.Body).Decode(&user)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		dao.Insert(NewUser(user.Id, user.Name, user.Email))
	})

	router.HandleFunc("GET /users", func(w http.ResponseWriter, r *http.Request) {
		users := dao.GetAll()
		j, err := json.Marshal(users)
		if err != nil {
			fmt.Printf("Error: %s", err.Error())
		} else {
			fmt.Fprintf(w, "%s", string(j))
		}
	})

	router.HandleFunc("GET /users/{id}", func(w http.ResponseWriter, r *http.Request) {
		id := r.PathValue("id")
		user := dao.Get(id)
		j, err := json.Marshal(user)
		if err != nil {
			fmt.Printf("Error: %s", err.Error())
		} else {
			fmt.Fprintf(w, "%s", string(j))
		}
	})

	/*
		router.HandleFunc("PATCH /users/{id}", func(w http.ResponseWriter, r *http.Request) {
			id := r.PathValue("id")
			fmt.Println("update a user by id", id)
		})
	*/

	router.HandleFunc("PATCH /users/{rest...}", func(w http.ResponseWriter, r *http.Request) {
		rest := r.PathValue("rest")
		fmt.Println("wild card route", rest)
	})

	router.HandleFunc("PUT /users", func(w http.ResponseWriter, r *http.Request) {
		var user User
		err := json.NewDecoder(r.Body).Decode(&user)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		dao.Update(NewUser(user.Id, user.Name, user.Email))
	})

	router.HandleFunc("DELETE /users/{id}", func(w http.ResponseWriter, r *http.Request) {
		id := r.PathValue("id")
		dao.Delete(id)
	})

	err := http.ListenAndServe("localhost:8080", router)
	if err != nil {
		fmt.Println(err.Error())
	}
}