Vamos tentar escrever um pequeno treinamento, mas um sistema de informações bastante completo que consiste em uma parte do servidor no Go e um aplicativo Web cliente em Javascript + Vue JS.
Primeiro, algumas palavras sobre o que é esse aplicativo e para que serve. Algum tempo atrás, surgiu a minha pergunta sobre como economizar uma certa quantia de dinheiro que eu havia formado. Mesmo para mim, uma pessoa distante do mundo das finanças, era óbvio que manter dinheiro em dinheiro era ruim por pelo menos duas razões:
- Dinheiro consome inflação (risco inflacionário)
- O rublo pode se depreciar (risco de taxa de câmbio)
Decidiu-se estudar o problema e escolher a ferramenta de investimento apropriada. Os principais critérios foram confiabilidade e proteção das economias contra os riscos acima.
Estudei a questão e, como resultado, concluí que a única ferramenta de investimento adequada para um russo são os fundos negociados em bolsa de valores (ETF) e os que são negociados na Bolsa de Moscou.
Assim, proponho escrever um aplicativo de treinamento que mostre a rentabilidade de todos os ETFs apresentados na Bolsa de Moscou.
Você pode dizer que essa lucratividade pode ser visualizada no próprio site de intercâmbio, e o aplicativo, pelo menos para treinamento, deve ser um pouco útil. Concordo, portanto, tentaremos exibir algum retorno real condicional das ações. Com esse retorno real condicional, quero dizer a taxa de retorno ajustada pela inflação na Rússia.
Na primeira parte do artigo, analisaremos a parte do servidor do aplicativo. Nosso back-end está escrito em Go e, durante o desenvolvimento, tentaremos aplicar recursos da linguagem como execução paralela de código, interfaces, testes e muito mais.
Requisitos TK:
- A parte do servidor do aplicativo deve fornecer, mediante solicitação, dados sobre cotações de todos os ETFs do Moscow Exchange e dados de inflação para todos os meses de negociação de cada documento
- A parte do servidor do aplicativo deve oferecer suporte a vários provedores de data warehouse, a alternância entre provedores não deve exigir alterações de código
- A parte do servidor do aplicativo deve fornecer a API via protocolo http para receber dados do armazenamento
Então, vamos projetar a arquitetura de software da parte do servidor do nosso sistema.
Primeiro , apresentaremos a estrutura do pacote do aplicativo. De acordo com a declaração de trabalho, o aplicativo consistirá em um servidor da web que fornecerá a API REST e fornecerá os arquivos do nosso aplicativo da web (posteriormente escreveremos o SPA no Vue). Além disso, de acordo com o ToR, devemos fazer vários pacotes para provedores de data warehouse.
Neste ponto, devemos nos debruçar com mais detalhes. Como posso fornecer a capacidade de alternar entre provedores de alguma funcionalidade no Go? Resposta: usando interfaces. Portanto, precisaremos desenvolver uma interface (contrato) para pacotes, cada um deles executando um contrato para seu próprio tipo de armazenamento. No artigo, consideraremos o armazenamento de dados na RAM, mas por analogia, você pode adicionar facilmente qualquer DBMS. A estrutura final do pacote será a seguinte:
Em segundo lugar , vamos decidir sobre os tipos de dados nos quais armazenaremos as informações recebidas e o contrato para os provedores de armazenamento.
Vamos precisar de tipos de dados para cotações de ações e inflação. Tomaremos cotações e inflação por meses, essa escala é bastante adequada para instrumentos não especulativos como o ETF.
O contrato exigirá a disponibilidade de métodos para preencher o armazenamento com dados do servidor Mosbirzha (inicialização) e fornecer dados de cotação mediante solicitação. Tudo é extremamente simples.
Como resultado, colocamos os tipos para armazenar cotações e a interface no módulo de armazenamento:
Para simplificar, codificamos os dados de inflação no módulo do servidor:
var inflation = []struct { Year int Values [12]float64 }{ { Year: 2013, Values: [12]float64{0.97, 0.56, 0.34, 0.51, 0.66, 0.42, 0.82, 0.14, 0.21, 0.57, 0.56, 0.51}, }, { Year: 2014, Values: [12]float64{0.59, 0.70, 1.02, 0.90, 0.90, 0.62, 0.49, 0.24, 0.65, 0.82, 1.28, 2.62}, }, { Year: 2015, Values: [12]float64{3.85, 2.22, 1.21, 0.46, 0.35, 0.19, 0.80, 0.35, 0.57, 0.74, 0.75, 0.77}, }, { Year: 2016, Values: [12]float64{0.96, 0.63, 0.46, 0.44, 0.41, 0.36, 0.54, 0.01, 0.17, 0.43, 0.44, 0.40}, }, { Year: 2017, Values: [12]float64{0.62, 0.22, 0.13, 0.33, 0.37, 0.61, 0.07, -0.54, -0.15, 0.20, 0.22, 0.42}, }, { Year: 2018, Values: [12]float64{0.31, 0.21, 0.29, 0.38, 0.38, 0.49, 0.27, 0.01, 0.16, 0.35, 0.50, 0.84}, }, }
Terceiro , vamos descrever os pontos finais da nossa API. Haverá apenas dois: para cotações e inflação. Somente método HTTP GET.
Na verdade, o recebimento e processamento de dados do site Mosbirzi é realizado no método de inicialização. Tomamos os dados de acordo com a
ajuda na API de troca .
O que você deve prestar atenção: somos forçados a usar uma solicitação separada para cada segurança (e já existem algumas dúzias). Executar a inicialização de dados sequencialmente, em um único encadeamento, levaria muito tempo. Portanto, usaremos o orgulho das go-goroutines. Preste atenção ao seguinte trecho de código:
Na função de inicialização de dados, paralelizamos solicitações ao servidor. Na prática, essa análise de site tem vários problemas:
- Pode levar ao bloqueio automático de solicitações devido a suspeita de DoS
- Você deve usar o módulo de contexto ou o canal de controle para forçar o término da goroutina.
- Você precisa usar o canal para retornar erros da goroutine
Por simplicidade, todos esses pontos são omitidos.
Para os propósitos do programa de treinamento, o roteador de solicitação HTTP embutido é suficiente para nós. Em sistemas mais complexos, você provavelmente deseja usar outro. Pessoalmente, eu uso o roteador do projeto Gorilla, mas em geral existem muitos deles.
Posteriormente, adicionaremos um ponto para fazer upload de arquivos do nosso aplicativo da web. No futuro, direi que, para isso, você deve simplesmente usar o retorno do conteúdo do arquivo.
Então, vamos escrever nosso servidor:
Não fornecerei o código de implementação de armazenamento na memória aqui, tudo está disponível no
Github .
Para testar nossa API:
inflaçãocitaçõesIsso completa a primeira parte do artigo. Na segunda parte, escreveremos testes e medições de desempenho para nossos pacotes. Na terceira parte, desenvolveremos um aplicativo da web.