Sei sulla pagina 1di 49

Golang Web Services

Construindo Web Services com Golang


#dev #golang #webservices

5 de Fevereiro 2015 – CPBR8


Edson Hilios
Engenheiro @ Centro de Inovação Telefónica | Vivo
http://edson.hilios.com.br
Agenda
1. Visão geral do Go
2. Introdução a sintaxe
3. Configurando seu workspace
4. Construindo um web service
Go aka Golang
É uma linguagem desenvolvida por
engenheiros do Google em 2007.

Com o objetivo de juntar o poder de linguagens


como C e Java com a facilidade de escrita e
manutenção de código do Python.
Quem use Go?
Por quê Go?
● Sintaxe simples*
● Alta performance
● Excelente biblioteca padrão
● Compila rapido
● Facil manipulação de threads
Ferramentas
0 $ go build // Compila gerando um executavel
1 $ go run // Compila sem gerar um executavel
2 $ go get // Baixa e instala um pacote
3 $ go install // Compila e instala um pacote
4 $ go test // Executa os testes de um pacote
5 $ go fmt // Formata seu código (Go code-style)
6 $ go vet // Encontra erros que não de compilação
7 $ godoc // Gera a documentação
8
9
10
Sintaxe
Caracteristicas
● Compilada
● Tipada com inferencia
● Possui primitivos, hash-maps, slices e arrays
● Total acesso a memória
● Garbage-collected
● Não é orientada a objetos
● Paradigmas de linguagem funcional
Hello, World!
0 package main
1
2 import "fmt"
3
4 func main() {
5 fmt.Println("Hello, World!")
6 }
7
8
9
10 hello.go
Executando
0 $ go run hello.go
1 Hello, World!
2
3

Execute o comando go run no seu shell.


Variaveis
0 package main
1
2 import "fmt"
3
4 func main() {
5 var helloWord string
6 helloWord = "Hello, World!"
7
8 fmt.Println(helloWord)
9 }
10
Variaveis
0 package main
1
2 import "fmt"
3
4 func main() {
5 helloWord := "Hello, World!"
6
7 fmt.Println(helloWord)
8 }
9
10
Variaveis
0 const HELLO_WORLD = "Hello, World!"
1
2 var (
3 boleano bool
4 inteiro int
5 pontoFlutuante float64
6 arrayDeStrings []string
7 matriz3por3 [3][3]int
8 mapaDeInteiros map[int]string
9 ponteiro *string
10 )
Condicionais
0 import "log"
1
2 if len(x) > 0 {
3 log.Println("Array")
4 }
5
6 file, err := os.Open("arquivo.txt")
7 if err != nil {
8 log.Fatal(err)
9 }
10
Loops
0 sum := 0
1 for i := 0; i < 10; i++ {
2 sum += i
3 }
4
5 sum := 0
6 for i, value := range array {
7 sum += value
8 }
9
10
Funções
0 func HelloTo(name string) string {
1 fmt.Printf("Hello, %s!", name)
2 }
3 // Documentação da função
4 func MultipleReturn (a int) (int, error) {
5 var err error
6 if True {
7 err = fmt.Errorf("Algo errado!")
8 }
9 return a + 1, err
10 }
Structs
0 type Carro struct {
1 Fabricante, Modelo, Cor string
2 Portas int
3 }
4
5 focus := Carro{Fabricante: "Ford", Modelo: "Focus",
6 Cor: "Preto", Portas: 5}
7
8 cruze := new(Carro)
9 cruze.Fabricante = "Chevrolet"
10 // ...
Métodos
0 func (c *Carro) Buzinar() {
1 fmt.Println("Honk!")
2 }
3
4 func (c *Carro) String() string {
5 return fmt.Srintf("%s %s cor %d %d portas",
6 c.Fabricante, c.Modelo, c.Cor, c.Portas)
7 }
8
9 // Executa a função
10 focus.Buzinar()
Interfaces
0 type RestService interface {
1 Get(data url.Values) http.HandlerFunc
2 Post(data url.Values) http.HandlerFunc
3 Put(data url.Values) http.HandlerFunc
4 Delete(data url.Values) http.HandlerFunc
5 }
6
7
8
9
10
Workspace
Estrutura de pastas
0 # ~/Golang
1 # |-- bin/
2 # |-- src/
3 # |-- pkg/
4
5 mkdir -p ~/Golang/{bin,src,pkg}
6
7
8
9
10
Workspace
0 /*
1 ~/Golang
2 |-- src/
3 | |-- meuprojeto.com/
4 | | |-- funcionalidade/
5 | | | |-- *.go
6 */
7 import "meuprojeto.com/funcionalidade"
8
9
10
Workspace
0 # Configura o caminho de importação/instalação
1 export GOPATH=$(cd ~/Golang; pwd)
2 # Adiciona aos executaveis do OS
3 export PATH=$PATH:$GOPATH/bin
4
5
6
7
8
9
10 ~/.bash_profile
Web Service
http://hilios.github.io/cpbr8app/
Projeto
Verbo Rota Descrição Task

GET /tasks Lista todas as Tarefas ID pk

GET /task?id=* Retorna uma Tarefa Description string

POST /task?id=* Cria uma nova Tarefa Completed bool

PUT /task?id=* Atualiza uma Tarefa

DELETE /task?id=* Deleta uma Tarefa


Estrutura
0 # $GOPATH/src/cpbr8app/
1 # |-- controllers.go
2 # |-- core.go
3 # |-- db.go
4 # |-- main.go
5 # |-- models.go
6
7 $ mkdir -p $GOPATH/src/cpbr8app
8 $ cd $GOPATH/src/cpbr8app
9
10
Hello, Web!
0 package main
1
1
2
2 import "net/http"
3
3
4 func helloHandler(rw http.ResponseWriter, r *http.Request)
4
5 {
5
6 fmt.Fprint(rw, "Hello, Web!")
6
7 }
7
8
8
9 func main() {
9
10 http.HandleFunc("/", helloHandler)
11
10 http.ListenAndServe(":8000", nil) main.go
12 }
http://localhost:8000
0 import (
1 "encoding/json"
2 "net/http"
3 "net/url"
4 )
5
6 // Interface de um serviço REST
7 type RestInterface interface {
8 Get(values url.Values) (int, interface{})
9 Post(values url.Values) (int, interface{})
10 Put(values url.Values) (int, interface{})
11 Delete(values url.Values) (int, interface{})
12 }
13
14
15 core.go
15
0 func RestController(i RestInterface) http.HandlerFunc {
16
1 return func(rw http.ResponseWriter, r *http.Request) {
17
2 r.ParseForm() // Coleta os dados enviados
18
3 values := r.Form
19
4 method := r.Method
20
5 switch method {
21
6 case "GET":
22
7 code, data := i.Get(values)
23
8 case "POST":
24
9 code, data := i.Post(values)
10
25 case "PUT":
11
26 code, data := i.Put(values)
12
27 // ... o mesmo para DELETE
13
28 default:
14
29 code, data := 405, nil
15
30 core.go
}
0
31 // ... continuação
1
32 j, err := json.Marshal(data)
2
33 if err != nil {
3
34 code = 500 // Internal Server Error
4
35 }
5
363 // Lida quando ocorre um erro
6
7 if code >= 400 {
7
38 http.Error(rw, http.StatusText(code), code)
8
39 return
9
40 }
10
41 // Escreve o response
11
42 rw.WriteHeader(code)
12
43 rw.Write(j)
13
44 }
14
45 }
15 core.go
46
Instalando dependencias
0 # Instala a biblioteca em ~/Golang/src
1 $ go get labix.org/v2/mgo
2
3

MGO é o driver de MongoDB para Golang, o


comando go get baixa o repositório para o seu
workspace.
Banco de dados
0 import "labix.org/v2/mgo"
1
2 var conn *MongoConnection
3
4 func init() {
5 conn = new(MongoConnection)
6 }
7
8
9
10 db.go
0 type MongoConnection struct {
1 session *mgo.Session
2 }
3
4 func (m *MongoConnection) Connect() {
5 session, err := mgo.Dial("localhost")
6 if err != nil {
7 panic(err)
8 }
9 m.session = session
10 }
11
12 func (m *MongoConnection) Close() {
13 m.session.Close()
14 }
15 db.go
0 // Retorna a conexão com o BD global
1 func GetMongoConnection() (*MongoConnection) {
2 return conn
3 }
4
5 // Retorna uma conexão com o Banco e a sessão utilizada
6 func GetDatabase() (*mgo.Database, *mgo.Session) {
7 session := conn.session.Copy()
8 return session.DB("cpbr8app"), session
9 }
10
11
12
13
14
15 db.go
Conectando ao BD
0 func main() {
1 db := GetMongoConnection()
2 db.Connect()
3 // Executa somente após esta função terminar
4 defer db.Close()
5
6 http.HandleFunc("/", helloHandler)
7 http.ListenAndServe(":8000", nil)
8 }
9
10 main.go
Modelo
0 import "labix.org/v2/mgo/bson"
1
2 type Task struct {
3 Id bson.ObjectId `bson:"_id" json:"id"`
4 Description string `bson:"desc" json:"desc"`
5 Completed bool `bson:"ok" json:"ok"`
6 }
7
8 type TaskList struct {
9 Tasks []Task `json:tasks`
10 } models.go
Modelo
0 func GetTaskList(db *mgo.Database) *TaskList {
1 var tasks []Task
2
3 collection := db.C("tasks")
4 collection.Find(nil).All(&tasks)
5
6 return &TaskList{tasks}
7 }
8
9
10 models.go
Controlador
0 import "net/url"
1
1
2
2 type TasksController struct{}
3
3
4 // Retorna uma lista com todas as Tasks
4
5 func (t *TasksController) Get(v url.Values) (int, i{}) {
5
6 db, s := GetDatabase()
6
7 defer s.Close()
7
8
8
9 return 200, GetTaskList(db)
9
10 }
11
10 controllers.go
12
Rotas
0 func main() {
1 // ... conexão com o BD
2
3 tasks := new(TasksController)
4 http.HandleFunc("/tasks", RestController(tasks))
5
6 http.HandleFunc("/", helloHandler)
7 http.ListenAndServe(":8000", nil)
8 }
9
10 main.go
http://localhost:8000/tasks
Modelo
0 func GetTaskById(db *mgo.Database, id string) *Task {
1 var task Task
2 oid := mgo.ObjectIdHex(id)
3
4 collection := db.C("tasks")
5 collection.FindId(oid).One(&task)
6
7 return &task
8 }
9
10 models.go
Controlador
0 type TaskController struct{}
1 // Retorna a task pelo ID
2 func (t *TasksController) Get(v url.Values) (int, i{}) {
3 db, s := GetDatabase()
defer s.Close()
4
5 task := GetTaskById(v.Get("id"))
6 if task == nil {
7 return 404, nil
8 }
9 return 200, task
10 } controllers.go
Rotas
0 func main() {
1 // ...
2
3 task := new(TaskController)
4 http.HandleFunc("/task", RestController(task))
5
6 // ...
7 }
8
9
10 main.go
http://localhost:8000/task?id=*
Code @ GitHub
http://github.com/hilios/cpbr8app/

● POST, PUT, DELETE


● Suporte a CORS
● App em AngularJS
Tks!
Golang ref: http://gobyexample.com

Twitter: @hilios
Site: http://edson.hilios.com.br
Apresentação: http://speakerdeck.com/hilios
GitHub: http://github.com/hilios

Potrebbero piacerti anche