GoFrame: Fluxo de Execução e Práticas de Desenvolvimento

Fluxo de Execução e Princípios do Framework

O framework GoFrame segue um processo estruturado para inicialização e tratamento de requisições. Aqui estão os pontos-chave:

  • Ordem de Inicialização: O processo começa com a importação de pacotes, seguida pela execução das funções init() de cada pacote, e finalmente a função main().
  • Cadeia de Middleware: As requisições passam pelos middlewares na ordem de registro, enquanto as respostas retornam na ordem inversa.
  • Correspondência de Rotas: A correspondência é feita com base no caminho da URL e no método HTTP, garantindo precisão.
  • Ciclo de Vida da Requisição: Inclui desde o recebimento até a conclusão da resposta, abrangendo todas as etapas de processamento.
  • Tratamento de Erros: Os erros são gerenciados tanto nos middlewares quanto nos controladores para robustez.

Detalhes sobre o processo de importação:

  1. Importação recursiva de todas as dependências.
  2. Inicialização de variáveis em nível de pacote.
  3. Execução das funções init() de cada pacote.

Aspectos Essenciais para Desenvolvedores

Compreenda os seguintes mecanismos do GoFrame:

  • O registro de rotas ocorre imediatamente, vinculando URLs a métodos de controlador, mas a invocação do controlador é adiada até uma requisição correspondente.
  • O método s.Group() executa seu callback instantaneamente para registrar regras de rota.
  • Os métodos de controlador só são chamados quando uma requisição HTTP é correspondida.
  • Os middlewares são executados sequencialmente durante a requisição, não no momento do registro.

Inicialização e Configuração do Servidor

Quando um programa Go inicia, as constantes e variáveis em nível de pacote são inicializadas primeiro, seguidas pelas funções init() na ordem de importação.

Após a inicialização, a função main() é executada. Aqui, o servidor padrão é obtido via g.Server(), e configurações básicas como porta e diretórios estáticos são definidas.

Registro de Componentes e Início do Servidor

Middlewares: Use s.Use() para registrar middlewares globais, como CORS, autenticação e logging. Eles processam requisições antes do roteamento.

Rotas: Utilize s.Group() para definir grupos de rotas, associando caminhos a métodos de controlador. Esses métodos são executados apenas quando há correspondência.

Após o registro, chame s.Run() para iniciar o servidor, que ficará bloqueado escutando requisições na porta configurada.

Ciclo de Vida da Requisição HTTP

  1. Filtragem por Middleware: A requisição passa por todos os middlewares registrados globalmente.
  2. Correspondência de Rota: O URL e o método HTTP são usados para localizar a rota e o controlador correspondentes.
  3. Execução da Lógica de Negócio: O método do controlador é invocado, processando a lógica e retornando uma resposta.
  4. Retorno da Resposta: A resposta é tratada pelos middlewares antes de ser enviada ao cliente.

Para uma inicialização explícita, consulte a documentação oficial. O framework também suporta reinicialização suave para atualizações sem interrupção.

Desenvolvimento com GoFrame

Assegure uma estrutura de projeto adequada. Para criar um novo projeto, use comandos como:

go mod init nome-do-projeto
go get -u -v github.com/gogf/gf/v2
go mod tidy

Para utilizar a estrutura de diretórios recomendada pelo GoFrame, instale a ferramenta CLI e inicialize o projeto:

go install github.com/gogf/gf/cmd/gf/v2@latest
gf init nome-do-app
gf up
cd nome-do-app && gf run main.go

Exemplo básico de código para um aplicativo:

package main

import (
    "log"
    "github.com/gogf/gf/v2"
)

func main() {
    log.Printf("GoFrame versão: %s", gf.VERSION)
}

Trabalhando com Banco de Dados e DAOs

Ao criar tabelas no banco de dados, utilize o comando gf gen dao para gerar camadas de acesso a dados. Isso produz arquivos em diretórios específicos:

  • internal/model/do/ para estruturas de escrita de dados.
  • internal/model/entity/ para estruturas de leitura de dados.
  • internal/dao/ para objetos de acesso a dados extensíveis.
  • internal/dao/internal/ para implementações internas, não expostas.

Personalize os caminhos de geração no arquivo de configuração YAML:

dao:
  - link: "mysql:usuario:senha@tcp(localhost:3306)/nome_do_banco"
    path: "./internal"
    daoPath: "/dao/plataforma"

Definindo APIs e Controladores

Para criar APIs, defina interfaces em api/usuarios/v1/. Use gf gen ctrl para gerar controladores correspondentes. A lógica de negócio é implementada em internal/logic/.

Regras de validação e internacionalização podem ser configuradas nos arquivos de API e na pasta manifest/i18n/.

Leitura e Escrita de Dados

Utilize as estruturas do para operações de escrita e entity para leitura. Os dados fluem através dessas camadas, garantindo separação de responsabilidades.

Funções Utilitárias Comuns

Aqui estão algumas funções úteis adaptadas para o desenvolvimento:

package utils

import (
    "context"
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/net/ghttp"
)

// Verifica se um elemento existe em um slice.
func ItemPresentInList[T comparable](slice []T, target T) bool {
    for _, item := range slice {
        if item == target {
            return true
        }
    }
    return false
}

// Estrutura padrão para respostas JSON.
type ApiResp struct {
    Status  int         `json:"status"`
    Message string      `json:"message"`
    Payload interface{} `json:"payload"`
}

// Envia uma resposta JSON.
func SendJson(resp *ghttp.Request, status int, message string, payload ...interface{}) {
    data := interface{}(nil)
    if len(payload) > 0 {
        data = payload[0]
    }
    resp.Response.WriteJson(ApiResp{
        Status:  status,
        Message: message,
        Payload: data,
    })
}

// Envia uma resposta JSON e encerra a requisição.
func SendJsonAndExit(resp *ghttp.Request, status int, message string, payload ...interface{}) {
    SendJson(resp, status, message, payload...)
    resp.Exit()
}

Parra tratamento de erros, funções auxiliares podem ser usadas:

package errlib

import (
    "context"
    "github.com/gogf/gf/v2/frame/g"
)

// Lança um erro se não for nulo.
func ErrIsNil(ctx context.Context, err error, msg ...string) {
    if err != nil {
        g.Log().Error(ctx, err.Error())
        if len(msg) > 0 {
            panic(msg[0])
        }
        panic(err.Error())
    }
}

Outros utilitários incluem manipulação de arquivos, criptografia e serviços HTTP, que podem ser adaptados conforme necessário.

Tags: GoFrame Golang middleware Routing ORM

Publicado em 6-1 11:39 por Thomas