Aviso
Nilaway está atualmente em desenvolvimento ativo: falsos positivos e mudanças de quebra podem acontecer. Agradecemos muito qualquer feedback e contribuições!
Nilaway é uma ferramenta de análise estática que busca ajudar os desenvolvedores a evitar nulos em pânico na produção, pegando -os no tempo de compilação, em vez de tempo de execução. A Nilaway é semelhante ao analisador de Nilness padrão, no entanto, emprega técnicas de análise estática muito mais sofisticadas e poderosas para rastrear os fluxos de NIL em um pacote, bem como em pacotes, e relatar erros que fornecem aos usuários os fluxos de nilades para mais facilitar a depuração.
Nilaway desfruta de três propriedades principais que o destacam:
É totalmente automatizado : Nilaway está equipado com um mecanismo de inferência, tornando-se que não requer nenhuma informação adicional dos desenvolvedores (por exemplo, anotações) além do código GO padrão.
É rápido : projetamos Nilaway para ser rápido e escalável, tornando -o adequado para bases de código grandes. Em nossas medições, observamos menos de 5% de sobrecarga no tempo de construção quando Nilaway está ativado. Também estamos constantemente aplicando otimizações para reduzir ainda mais sua pegada.
É prático : não impede todo o seu número possível de pânico em seu código, mas capta a maior parte do pânico potencial que observamos na produção, permitindo que Nilaway mantenha um bom equilíbrio entre utilidade e sobrecarga de tempo de construção.
? Para uma discussão técnica mais detalhada, consulte nosso wiki, blog de engenharia e papel (WIP).
O NILAWAY é implementado usando o GO/análise padrão, facilitando a integração dos drivers de analisador existentes (ou seja, Golangci-Lint, Nogo ou executa como verificador independente).
Importante
Por padrão, o Nilaway analisa todos o código Go, incluindo as bibliotecas e dependências padrão. Isso ajuda a Nilaway a entender melhor as dependências do formulário de código e reduzir seus falsos negativos. No entanto, isso também incorreria em um custo de desempenho significativo (apenas uma vez para os motoristas com suporte modular) e aumentaria o número de erros não ativos nas dependências, para grandes projetos de GO com muitas dependências.
É altamente recomendável usar o sinalizador de incluir PKGS para restringir a análise ao código do seu projeto exclusivamente. Isso direciona a Nilaway a pular a análise de dependências (por exemplo, bibliotecas de terceiros), permitindo que você se concentre apenas em possíveis pânicos nulos relatados por Nilaway em seu código de primeira parte!
Importante
Devido à sofisticação das análises que Nilaway faz, Nilaway armazena em cache suas descobertas sobre um pacote específico através do mecanismo de fato da estrutura GO/Analysis. Portanto, é altamente recomendável alavancar um driver que suporta análise modular (ou seja, Bazel/Nogo ou Golangci-Lint, mas não o verificador independente, pois armazena todos os fatos na memória) para um melhor desempenho em grandes projetos. O verificador independente é fornecido mais para fins de avaliação, pois é fácil começar.
Instale o binário da fonte em execução:
go install go.uber.org/nilaway/cmd/nilaway@latestEm seguida, execute o linhador por:
nilaway -include-pkgs= " <YOUR_PKG_PREFIX>,<YOUR_PKG_PREFIX_2> " ./...Dica
Desative a bandeira pretty-print quando a saída como JSON:
nilaway -json -pretty-print=false -include-pkgs= " <YOUR_PKG_PREFIX>,<YOUR_PKG_PREFIX_2> " ./...Nilaway, em sua forma atual, pode relatar falsos positivos. Infelizmente, isso dificulta sua fusão imediata no Golangci-Lint e é oferecida como um linhador (ver PR#4045). Portanto, você precisa construir o Nilaway como um plug-in para o Golangci-Lint para ser executado como um linhador privado. Existem dois sistemas de plug-in no Golangci-Lint, e é muito mais fácil usar o sistema de plug-in do módulo (introduzido desde a v1.57.0), e é a única abordagem suportada a ser executada em Nilaway em Golangci-Lint.
(1) Crie um arquivo .custom-gcl.yml na raiz do repositório Se você não o fez, adicione o seguinte conteúdo:
# This has to be >= v1.57.0 for module plugin system support.
version : v1.57.0
plugins :
- module : " go.uber.org/nilaway "
import : " go.uber.org/nilaway/cmd/gclplugin "
version : latest # Or a fixed version for reproducible builds. (2) Adicione Nilaway ao arquivo de configuração do Linter .golangci.yaml :
linters-settings :
custom :
nilaway :
type : " module "
description : Static analysis tool to detect potential nil panics in Go code.
settings :
# Settings must be a "map from string to string" to mimic command line flags: the keys are
# flag names and the values are the values to the particular flags.
include-pkgs : " <YOUR_PACKAGE_PREFIXES> "
# NilAway can be referred to as `nilaway` just like any other golangci-lint analyzers in other
# parts of the configuration file.(3) Construir um binário personalizado de Golangci-Lint com Nilaway incluído:
# Note that your `golangci-lint` to bootstrap the custom binary must also be version >= v1.57.0.
$ golangci-lint custom Por padrão, o binário personalizado será construído em . com o nome custom-gcl , que pode ser ainda mais personalizado no arquivo .custom-gcl.yml (consulte o sistema de plug-in do módulo para obter instruções).
Dica
Cache o binário personalizado para evitar que ele seja criado novamente para economizar recursos, você pode usar o hash do arquivo .custom-gcl.yml como tecla de cache se estiver usando uma versão fixa do Nilaway. Se você estiver usando a versão latest como Nilaway, poderá anexar a data de compilação à chave de cache para forçar a expiração do cache após um determinado período de tempo.
(4) Execute o binário personalizado em vez de golangci-lint :
# Arguments are the same as `golangci-lint`.
$ ./custom-gcl run ./...Correr com Bazel/Nogo requer um pouco mais de esforços. Primeiro, siga as instruções de Regras_Go, Gazelle e Nogo para configurar seu projeto Go, de modo que ele possa ser construído com Bazel/Nogo sem ou não ou conjunto de linters padrão configurado. Então,
(1) Adicione import _ "go.uber.org/nilaway" ao seu arquivo tools.go (ou outro arquivo que você usa para configurar dependências de ferramentas, consulte como posso rastrear as dependências de ferramentas para um módulo? Da documentação GO Modules) para evitar go mod tidy de remover o Nilaway como uma dependência da ferramenta.
(2) Execute os seguintes comandos para adicionar Nilaway como uma dependência de ferramentas ao seu projeto:
# Get NilAway as a dependency, as well as getting its transitive dependencies in go.mod file.
$ go get go.uber.org/nilaway@latest
# This should not remove NilAway as a dependency in your go.mod file.
$ go mod tidy
# Run gazelle to sync dependencies from go.mod to WORKSPACE file.
$ bazel run //:gazelle -- update-repos -from_file=go.mod (3) Adicione as configurações Nilaway às Nogo (geralmente no arquivo BUILD.bazel de nível superior):
nogo(
name = "my_nogo",
visibility = ["//visibility:public"], # must have public visibility
deps = [
+++ "@org_uber_go_nilaway//:go_default_library",
],
config = "config.json",
) (4) Executar a Bazel Build para ver a Nilaway trabalhando (qualquer erro do NOGO interrompe a construção da Bazel, você pode usar a bandeira --keep_going para solicitar que a Bazel construa o máximo possível):
$ bazel build --keep_going //...(5) Consulte a documentação do NOGO sobre como passar uma configuração JSON para o driver Nogo e veja nossa página do Wiki sobre como passar as configurações para Nilaway.
Vejamos alguns exemplos para ver como Nilaway pode ajudar a prevenir o Nil Panics.
// Example 1:
var p * P
if someCondition {
p = & P {}
}
print ( p . f ) // nilness reports NO error here, but NilAway does. Neste exemplo, a variável local p é inicializada apenas quando someCondition é verdadeira. No campo de acesso pf , um pânico pode ocorrer se someCondition for falsa. Nilaway é capaz de capturar esse fluxo potencial de nulo e relata o seguinte erro mostrando esse fluxo de nilades:
go.uber.org/example.go:12:9: error: Potential nil panic detected. Observed nil flow from source to dereference point:
- go.uber.org/example.go:12:9: unassigned variable `p` accessed field `f`
Se guardarmos essa desreferência com uma verificação de nilades ( if p != nil ), o erro desaparecerá.
Nilaway também é capaz de capturar nulos fluxos nas funções. Por exemplo, considere o seguinte snippet de código:
// Example 2:
func foo () * int {
return nil
}
func bar () {
print ( * foo ()) // nilness reports NO error here, but NilAway does.
} Neste exemplo, a função foo retorna um ponteiro nulo, que é desreferenciado diretamente na bar , resultando em pânico sempre que bar for chamada. Nilaway é capaz de capturar esse fluxo nulo potencial e relata o seguinte erro, descrevendo o fluxo de nilades através dos limites da função:
go.uber.org/example.go:23:13: error: Potential nil panic detected. Observed nil flow from source to dereference point:
- go.uber.org/example.go:20:14: literal `nil` returned from `foo()` in position 0
- go.uber.org/example.go:23:13: result 0 of `foo()` dereferenced
Observe que, no exemplo acima, foo não precisa necessariamente residir no mesmo pacote que bar . Nilaway também é capaz de rastrear os fluxos de NIL nos pacotes. Além disso, a Nilaway lida com construções de linguagem específicas para GO, como receptores, interfaces, afirmações de tipo, comutadores de tipo e muito mais.
Expomos um conjunto de sinalizadores através do mecanismo de passagem de sinalizador padrão em Go/análise. Verifique o Wiki/Configuração para ver os sinalizadores disponíveis e como passá -los usando diferentes drivers Linter.
Seguimos a mesma política de suporte da versão do projeto Go: apoiamos e testamos as duas últimas versões principais do GO.
Sinta -se à vontade para abrir um problema do GitHub se tiver alguma dúvida, relatórios de bugs e solicitações de recursos.
Adoraríamos que você contribuísse com Nilaway! Observe que, depois de criar uma solicitação de tração, você será solicitado a assinar nosso Contrato de Licença de Colaborador do Uber.
Este projeto é Copyright 2023 Uber Technologies, Inc. e licenciado no Apache 2.0.