Go: RESTful - um exemplo completo com persistência
De Aulas
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())
}
}