Created
October 28, 2022 17:58
-
-
Save rgs1/163732ef1277f408cdcfa749a7e11a6b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/json" | |
"fmt" | |
"log" | |
"net/http" | |
"net/mail" | |
"os" | |
) | |
var ( | |
logPath = "emails.log" | |
serverAddress = "127.0.0.1:8080" | |
) | |
// definicion de estructura | |
type Message struct { | |
Email string | |
} | |
// asignando un metodo a una estructura (OOP, pero sin mucha burocracia) | |
func (m *Message) valid() bool { | |
_, err := mail.ParseAddress(m.Email) | |
return err == nil | |
} | |
// defino una interface... | |
type Logger interface { | |
Save(m Message) | |
} | |
type LoggerImpl struct { | |
c chan Message | |
} | |
// Implementar todos los metodos de una interface nos hace adherir a la misma | |
func (l *LoggerImpl) Save(m Message) { | |
l.c <- m | |
} | |
func NewLoggerImpl() *LoggerImpl { | |
// Toma de punter explicita --> golang ahora sabe que este objeto tiene que vivir en el heap | |
return &LoggerImpl{ | |
c: make(chan Message), | |
} | |
} | |
func (l *LoggerImpl) run() { | |
f, err := os.OpenFile(logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) | |
if err != nil { | |
fmt.Println(err) | |
return | |
} | |
// Al salir de este metodo, cerrar el archivo (no tengo que preocuparme de cada return individual) | |
defer f.Close() | |
for { | |
// recibir un mensaje a traves del canal c | |
msg := <-l.c | |
fmt.Println(msg.Email) | |
// guardar | |
if _, err := f.WriteString(msg.Email + "\n"); err != nil { | |
fmt.Println(err) | |
} | |
} | |
} | |
func handler(w http.ResponseWriter, r *http.Request, l Logger) { | |
switch r.Method { | |
case "POST": | |
var msg Message | |
decoder := json.NewDecoder(r.Body) | |
err := decoder.Decode(&msg) | |
if err != nil { | |
http.Error(w, "decoding error", http.StatusBadRequest) | |
return | |
} | |
if !msg.valid() { | |
http.Error(w, "invalid email", http.StatusBadRequest) | |
return | |
} | |
if len(msg.Email) > 100 { | |
http.Error(w, "email too long", http.StatusBadRequest) | |
return | |
} | |
// Utilizar el canal para notificar al otro hilo o goroutine sobre el trabajo pendiente | |
// Esto es practicamente inmediato (depende del tamaño del canal), asi que no bloquea al usuario | |
l.Save(msg) | |
fmt.Fprintf(w, "ok\n") | |
default: | |
http.Error(w, "only POST is supported", http.StatusNotFound) | |
} | |
} | |
func main() { | |
l := NewLoggerImpl() // <-- inferencia de tipo | |
go l.run() // <-- concurrencia en una sola linea!! | |
// funciones definidas dentro de otra funcion | |
http.HandleFunc("/add-email", func(w http.ResponseWriter, r *http.Request) { | |
handler(w, r, l) | |
}) | |
// asignar y chequear en la misma linea | |
if err := http.ListenAndServe(serverAddress, nil); err != nil { | |
log.Fatal(err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment