
uma palavra persa que significa "pequeno" ou "li'l". É frequentemente usado para se referir a uma garota quando flerta (com o significado, garota li'l)
Dicionário Urbano
Bem -vindo ao KooCooloo : um projeto elegante e prático criado para otimizar o desenvolvimento de aplicações de Golang. Com uma arquitetura bem organizada, a KooCoCooloo integra recursos vitais, como manuseio de banco de dados e gerenciamento de configurações, exemplificando as melhores práticas na criação de aplicativos de repouso robustos com GO.
init : evita globais e as complexidades das funções init para simplificar as coisas. Aproveitando fx como nossa estrutura de injeção de dependência, o KooCoColoo entrega:
fx no teste com a mesma facilidade que na produção.Embarque em uma jornada com o KooChooloo e redefina sua abordagem para criar aplicativos RESTful em Go. Esteja você expandindo seu conjunto de habilidades ou criando uma base sólida para aplicações complexas, o KooCoCooloo é seu parceiro em design de software eficiente, limpo e escalável.
Primeiro de tudo, o pacote cmd contém os binários deste projeto com o uso da COBRA. É bom ter binários simples para tarefas como migrações de banco de dados que podem ser executadas na fase de iniciação do projeto. Cada binário possui seu main.go Register Register root.go cmd Aqui está um exemplo para a função de registro:
// Register server command.
func Register ( root * cobra. Command ) {
root . AddCommand (
& cobra. Command {
Use : "server" ,
Short : "Run server to serve the requests" ,
Run : func ( _ * cobra. Command , _ [] string ) {
fx . New (
fx . Provide ( config . Provide ),
fx . Invoke ( main ),
). Run ()
},
},
)
} Novamente, cada comando registra seu sinalizador por si só, por isso temos separação de outros comandos. Às vezes, precisamos ter bandeiras compartilhadas entre os comandos, então é melhor tê -los na configuração. Para o caso posterior, koanf pode nos ajudar com a estrutura como abaixo:
func Register ( fs * pflag. FlagSet ) {
fs . StringP (
"url" , "u" ,
nats . DefaultURL ,
fmt . Sprintf ( "nats server url(s) e.g. %s" , nats . DefaultURL ),
)
}Esta função registra sinalizadores compartilhados e, em seguida, carregamos a configuração com base nelas com a seguinte função:
k := koanf . New ( "." )
if err := k . Load ( posflag . Provider ( fs , "." , k ), nil ); err != nil {
log . Errorf ( "error loading config.yml: %s" , err )
}
if err := k . Unmarshal ( "" , & instance ); err != nil {
log . Fatalf ( "error unmarshalling config: %s" , err )
}A parte principal de cada aplicativo é sua configuração. Existem muitas maneiras de ter configuração no projeto, desde o arquivo de configuração até as variáveis de ambiente. Koanf tem todos eles em um belo pacote. Os principais pontos aqui são:
config e passará a ele em sua iniciação.O PS Koanf é muito melhor que o Viper por ter uma configuração digitada. Por configuração digitada, quero dizer que você tem uma estrutura definida para configuração e, em seguida, carregue a configuração de muitas fontes nela.
Para instalar o KOANF, você pode usar os seguintes comandos:
go get -u github.com/knadh/koanf/v2
go get -u github.com/knadh/koanf/providers/file
go get -u github.com/knadh/koanf/providers/env
go get -u github.com/knadh/koanf/providers/structs
go get -u github.com/knadh/koanf/parsers/toml Pacotes e serviços definidos no pacote domain usam apenas outros pacotes do domain sem usar nenhum pacotes de terceiros. Esses pacotes e serviços especificam os conceitos principais do domínio.
Há um pacote db responsável por conectar -se ao banco de dados. Este pacote usa a configuração do banco de dados definida no módulo config e cria uma instância do banco de dados. É uma boa ideia ping seu banco de dados aqui ter totalmente confiante na instância do banco de dados antes de avançar. Também para ter uma visão da saúde do banco de dados, você pode chamar essa função de ping periodicamente e relatar seu resultado com métricas (o que eu não fiz aqui).
Os modelos de projeto são definidos no pacote model . Esses modelos são usados internamente, mas podem ser usados em response ou pacote request . Não há estrutura para se comunicar com o banco de dados neste pacote.
Os repositórios são responsáveis por se comunicar com o banco de dados para armazenar ou recuperar modelos. Os repositórios são interface e há uma implementação concreta e ridicularizada para eles. A implementação do concreto é usada no código principal e ridicularizada é usada para testes. Observe que os testes para repositórios são sensíveis e são feitos com o banco de dados real.
O manipulador HTTP é definido no pacote handler . O Echo é uma estrutura HTTP incrível que tem tudo o que você precisa. Cada manipulador possui sua estrutura com um método Register que registra sua rota em um determinado grupo de rota. O Route Group é um conceito da Echo Framework para agrupar rotas sob um caminho pai específico. Cada manipulador tem o que precisa em sua estrutura. A estrutura do manipulador é criada no main.go e depois se registra em seu grupo.
type Healthz struct {}
// Handle shows server is up and running.
func ( h Healthz ) Handle ( c echo. Context ) error {
return c . NoContent ( http . StatusNoContent )
}
// Register registers the routes of healthz handler on given echo group.
func ( h Healthz ) Register ( g * echo. Group ) {
g . GET ( "/healthz" , h . Handle )
} Todas as métricas são coletadas usando Prometeu com base na telemetria aberta. Cada pacote possui sua metric.go . Para migrar de Prometheus para outro serviço, você só precisa alterar telemetry . As métricas não são globais e criaram para cada instância separadamente, graças ao design de telemetria aberta. Para ter um melhor controlador no terminal de métricas, há outro servidor HTTP definido no pacote de telemetry para monitoramento.
É bom ter pacotes separados para solicitações e respostas. Esses pacotes também contêm lógica de validação. Um dos bons pakcages de validação em Go é o Ozzo-Validator. Depois de fornecer o método Validate, depois de receber a solicitação, você pode validá -lo com seu método com facilidade.
Registrando um a parte mais importante do aplicativo. No começo, não há necessidade de ter algo mais do que logs simples. Mas, no futuro, você precisa obter logs e enviá -los para um sistema de agregação, porque quando seu sistema cresce a detecção de problemas dos registros de texto será ingerido.
O ZAP é o melhor logger para o registro da estrutura. zap obriga você a passar para o módulo filho e você também nomeia registradores com método Named . Usando o logger nomeado, você pode facilmente encontrar logs do módulo no seu agregador de log.
Este projeto requer apenas o MongoDB e você pode executá-lo com docker-compose .
cd deployments && docker-compose up -d
cd cmd/koochooloo/ && go build && ./koochooloocurl -X POST -d ' {"url": "https://elahe-dastan.github.io"} ' -H ' Content-Type: application/json ' 127.0.0.1:1378/api/urls
curl -L 127.0.0.1:1378/api/CKaniA checks.....................: 99.83% ✓ 2995 ✗ 5
data_received..............: 2.0 MB 64 kB/s
data_sent..................: 521 kB 17 kB/s
group_duration.............: avg=649.18ms min=153.18µs med=265.45ms max=30.95s p(90)=1.61s p(95)=2.06s
http_req_blocked...........: avg=14.12ms min=0s med=3µs max=1.65s p(90)=13µs p(95)=147.04µs
http_req_connecting........: avg=6.23ms min=0s med=0s max=1.36s p(90)=0s p(95)=0s
http_req_duration..........: avg=272.98ms min=0s med=127.99ms max=4.81s p(90)=830.93ms p(95)=1.29s
http_req_receiving.........: avg=125.23µs min=0s med=60µs max=11.21ms p(90)=228µs p(95)=363µs
http_req_sending...........: avg=50.78µs min=0s med=22µs max=7.28ms p(90)=86µs p(95)=138µs
http_req_tls_handshaking...: avg=7.86ms min=0s med=0s max=653.63ms p(90)=0s p(95)=0s
http_req_waiting...........: avg=272.8ms min=0s med=127.71ms max=4.81s p(90)=830.87ms p(95)=1.29s
http_reqs..................: 4000 129.093962/s
iteration_duration.........: avg=1.29s min=142.34ms med=1.04s max=30.97s p(90)=2.18s p(95)=2.64s
iterations.................: 1000 32.273491/s
vus........................: 100 min=100 max=100
vus_max....................: 100 min=100 max=100