Advertencia
Nilaway está actualmente en desarrollo activo: pueden ocurrir falsos positivos y cambios de ruptura. ¡Apreciamos mucho cualquier comentario y contribución!
Nilaway es una herramienta de análisis estático que busca ayudar a los desarrolladores a evitar los pánico nulo en la producción al atraparlos en el momento de la compilación en lugar del tiempo de ejecución. Nilaway es similar al analizador estándar de Nilness, sin embargo, emplea técnicas de análisis estático mucho más sofisticadas y poderosas para rastrear los flujos nil dentro de un paquete también en todos los paquetes e informa errores que proporcionan a los usuarios los flujos de nilitud para una depuración más fácil.
Nilaway disfruta de tres propiedades clave que lo hacen destacar:
Está completamente automatizado : Nilaway está equipado con un motor de inferencia, lo que hace que no requiere ninguna información adicional de los desarrolladores (p. Ej., Anotaciones) además del código GO estándar.
Es rápido : hemos diseñado a Nilaway para que sea rápido y escalable, lo que lo hace adecuado para grandes bases de código. En nuestras mediciones, hemos observado menos del 5% de sobrecarga de tiempo de construcción cuando Nilaway está habilitado. También aplicamos constantemente optimizaciones para reducir aún más su huella.
Es práctico : no evita todos los posibles pánico en su código, pero atrapa la mayoría de los posibles pánico nulo que hemos observado en la producción, lo que permite que Nilaway mantenga un buen equilibrio entre la utilidad y la sobrecarga de tiempo de construcción.
? Para una discusión técnica más detallada, consulte nuestro wiki, blog de ingeniería y documento (WIP).
Nilaway se implementa utilizando el análisis estándar/análisis, lo que facilita la integración con los controladores analizador existentes (es decir, Golangci-Lint, NoGO o ejecutándose como un verificador independiente).
Importante
De forma predeterminada, Nilaway analiza todo el código GO, incluidas las bibliotecas y dependencias estándar. Esto ayuda a Nilaway a comprender mejor las dependencias del formulario del código y reducir sus falsos negativos. Sin embargo, esto también incurriría en un costo de rendimiento significativo (solo una vez para los conductores con soporte modular) y aumentaría el número de errores no accionables en las dependencias, para grandes proyectos de GO con muchas dependencias.
Recomendamos encarecidamente usar el indicador de incluido PKGS para reducir el análisis al código de su proyecto exclusivamente. Esto le indica a Nilaway que se saltea las dependencias de análisis (por ejemplo, bibliotecas de terceros), lo que le permite concentrarse únicamente en posibles pánico nil informado por Nilaway en su código de primera parte.
Importante
Debido a la sofisticación de los análisis que hace Nilaway, Nilaway almacena en caché sus hallazgos sobre un paquete particular a través del mecanismo de hecho del marco GO/Análisis. Por lo tanto, se recomienda aprovechar un controlador que admite un análisis modular (es decir, bazel/nogo o golangci-lint, pero no el verificador independiente, ya que almacena todos los hechos en la memoria) para un mejor rendimiento en grandes proyectos. El verificador independiente se proporciona más para fines de evaluación, ya que es fácil comenzar.
Instale el binario desde la fuente ejecutando:
go install go.uber.org/nilaway/cmd/nilaway@latestLuego, ejecute el enlace por:
nilaway -include-pkgs= " <YOUR_PKG_PREFIX>,<YOUR_PKG_PREFIX_2> " ./...Consejo
Deshabilite el indicador pretty-print cuando salga como JSON:
nilaway -json -pretty-print=false -include-pkgs= " <YOUR_PKG_PREFIX>,<YOUR_PKG_PREFIX_2> " ./...Nilaway, en su forma actual, puede informar falsos positivos. Desafortunadamente, esto dificulta su fusión inmediata en Golangci-Lint y se ofrece como un linter (ver PR#4045). Por lo tanto, debe construir Nilaway como un complemento para Golangci-Lint para ser ejecutado como un enlace privado. Hay dos sistemas de complementos en Golangci-Lint, y es mucho más fácil usar el sistema de complementos del módulo (introducido desde V1.57.0), y es el único enfoque admitido para ejecutar Nilaway en Golangci-Lint.
(1) Cree un archivo .custom-gcl.yml en la raíz del repositorio si no lo ha hecho, agregue el siguiente contenido:
# 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) Agregue NILAWAY al archivo de configuración del líntula .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) Construya un binario personalizado Golangci-Lint con Nilaway incluido:
# Note that your `golangci-lint` to bootstrap the custom binary must also be version >= v1.57.0.
$ golangci-lint custom Por defecto, el binario personalizado se construirá en . Con el nombre custom-gcl , que se puede personalizar aún más en el archivo .custom-gcl.yml (consulte el sistema de complementos del módulo para obtener instrucciones).
Consejo
Almacena del binario personalizado Para evitar tener que construirlo nuevamente para guardar recursos, puede usar el hash del archivo .custom-gcl.yml como la clave de caché si está utilizando una versión fija de Nilaway. Si está utilizando latest versión como Nilaway, puede agregar la fecha de compilación a la clave de caché para forzar la expiración de caché después de cierto período de tiempo.
(4) Ejecute el binario personalizado en lugar de golangci-lint :
# Arguments are the same as `golangci-lint`.
$ ./custom-gcl run ./...Correr con Bazel/Nogo requiere un poco más de esfuerzos. Primero siga las instrucciones de Rules_Go, Gazelle y Nogo para configurar su proyecto GO de modo que pueda construirse con Bazel/Nogo con un conjunto no o un conjunto predeterminado de linters configurados. Entonces,
(1) go mod tidy import _ "go.uber.org/nilaway" a su archivo tools.go .
(2) Ejecute los siguientes comandos para agregar nilaway como dependencia de la herramienta a su proyecto:
# 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) Agregue NILAWAY a las configuraciones de Nogo (generalmente en el archivo BUILD.bazel de nivel superior):
nogo(
name = "my_nogo",
visibility = ["//visibility:public"], # must have public visibility
deps = [
+++ "@org_uber_go_nilaway//:go_default_library",
],
config = "config.json",
) (4) Ejecute la construcción de bazel para ver a Nilaway funcionando (cualquier error de Nogo detendrá la compilación de bazel, puede usar el indicador --keep_going para solicitar a Bazel que construya tanto como sea posible):
$ bazel build --keep_going //...(5) Vea la documentación de Nogo sobre cómo pasar un JSON de configuración al controlador Nogo, y vea nuestra página Wiki sobre cómo pasar las configuraciones a Nilaway.
Veamos algunos ejemplos para ver cómo Nilaway puede ayudar a prevenir los pánico nulo.
// Example 1:
var p * P
if someCondition {
p = & P {}
}
print ( p . f ) // nilness reports NO error here, but NilAway does. En este ejemplo, la variable local p solo se inicializa cuando someCondition es verdadera. En el campo de acceso pf , puede ocurrir un pánico si someCondition es falsa. Nilaway puede atrapar este posible flujo nulo e informa el siguiente error que muestra este flujo de nilitud:
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`
Si protegemos esta desertor con una verificación de nilismo ( if p != nil ), el error desaparece.
Nilaway también puede atrapar flujos nulos en las funciones. Por ejemplo, considere el siguiente fragmento de código:
// Example 2:
func foo () * int {
return nil
}
func bar () {
print ( * foo ()) // nilness reports NO error here, but NilAway does.
} En este ejemplo, la función foo devuelve un puntero nil, que se desamorea directamente en bar , lo que resulta en un pánico cada vez que se llama bar . Nilaway puede atrapar este flujo nulo potencial e informa el siguiente error, describiendo el flujo de Nilitud a través de los límites de la función:
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
Tenga en cuenta que en el ejemplo anterior, foo no necesariamente tiene que residir en el mismo paquete que bar . Nilaway también puede rastrear los flujos nulos en los paquetes. Además, Nilaway maneja construcciones de lenguaje específicas de GO, como receptores, interfaces, afirmaciones de tipo, interruptores de tipo y más.
Exponemos un conjunto de indicadores a través del mecanismo de aprobación de bandera estándar en GO/Análisis. Consulte Wiki/Configuración para ver los indicadores disponibles y cómo pasarlos utilizando diferentes controladores de enlace.
Seguimos la misma política de soporte de versión que el Proyecto GO: apoyamos y probamos las dos últimas versiones principales de GO.
No dude en abrir un problema de GitHub si tiene alguna pregunta, informes de errores y solicitudes de funciones.
¡Nos encantaría que contribuyas a Nilaway! Tenga en cuenta que una vez que cree una solicitud de extracción, se le pedirá que firme nuestro acuerdo de licencia de contribuyente de Uber.
Este proyecto es Copyright 2023 Uber Technologies, Inc., y con licencia bajo Apache 2.0.