¿Esta nueva propuesta de manejo de errores de Go resolverá el problema?

Hola a todos, soy pescaito frito.

Una característica importante del lenguaje Go es su mecanismo de error, por lo que básicamente revisaré y aprenderé todas las propuestas o debates de manejo de errores, y desarrollaré diferentes horizontes de pensamiento y soluciones.

Lo que comparto hoy es la propuesta " Simple Error Handling for Go 2 " propuesta por @Cristo García , ligeramente modificada, ¡aprendamos y discutamos con Jianyu!

Go debe seguir siendo Go

El punto central de esta propuesta es que Go debe seguir siendo Go, lo que significa que la transformación del manejo de errores debe cumplir con los siguientes principios:

  • Agregue la menor sintaxis posible.
  • Sea lo más claro y conveniente posible.

La "yo" de este artículo se refiere a la propuesta del autor @Cristo García, no a la fritura de pescado que estoy aprendiendo.

idea original

El autor de la propuesta original @PeterRk propuso las siguientes ideas:

func getDivisorFromDB(key string) (uint, error) {
	//...
}

func GetDivisor(key string) (uint, error) {
	exit := func(err error) (uint, error) {
		return 1, fmt.Errorf("fail to get divisor with key \"%s\": %v", key, err)
	}

	divisor := check(getDivisorFromDB(key), exit)

	//...
	return divisor, nil
}
复制代码

Ejemplo de uso:

divisor := check(getDivisorFromDB(key), exit) 
复制代码

Equivalente a existente:

divisor, err := getDivisorFromDB(key)
if err != nil {
	return exit(err)  //return err
}
复制代码

Los autores de la propuesta creen que esta es la dirección correcta y que podemos mejorarla (implicación: la corriente no es lo suficientemente buena).

Cuál es la pregunta

Hay dos problemas con esta idea original:

  • Contiene una declaración de devolución ambigua.
  • A veces, la abstracción es innecesaria y hace que el código sea más difícil de leer.

Idea Nueva

Por esta nueva idea necesita resolver los dos problemas anteriores, @Cristo García espera lograr mejores resultados. Con una simple modificación a la sintaxis, agregamos la palabra clave o.

Se pueden obtener los siguientes ejemplos:

divisor, err := getDivisorFromDB(key) or return exit(err)
复制代码

La palabra clave o recién agregada verificará si el último valor devuelto (que debe ser un tipo de error) es diferente de cero. De lo contrario, se ejecutará la función de la derecha.

También podemos omitir return y el código seguirá ejecutándose. Se descartará como en el código Go normal, para que la función sea más reutilizable.

El siguiente ejemplo:

func GetDivisor(key string) (divisor uint, err error) {
	divisor, err = getDivisorFromDB(key) or return
	return
}
复制代码

Es decir, la instrucción or return no va seguida de nada, es posible, y se descartará de forma predeterminada.

Escena especial: diferir

Esta sección es solo para debate, pero podemos aprovechar esta oportunidad para agregar la verificación de errores para diferir y ver si podemos hacer algo y obtener una nueva forma de manejarlo.

Idea central: sería muy interesante si no pudiéramos guardar el error devuelto en una variable y hacerlo o activarlo en diferido.

Ejemplo 1 a continuación:

defer f.Close() or return errHdl("", fmt.Errorf("couldn't close file"))
复制代码

Si la variable no se declara explícitamente, si el valor de retorno es del tipo incorrecto y no es igual a cero, la función en el lado derecho de o retorno se llama y procesa automáticamente.

Ejemplo 2 a continuación:

defer err := f.Close() or return errHdl("couldn't close file", err)
复制代码

Defina la variable err variable que acepta errores, que se puede usar pasando parámetros directamente a los parámetros de entrada de la función errHdl a través de la sintaxis de retorno o.

resultado

Se agregó una sintaxis nueva o de retorno y luego se comparó con el mecanismo de manejo de errores original para ver cómo.

nuevo:

func Foo(path string) ([]byte, error) {
	errHdlr := func(reason string, err error) ([]byte, error) {
		return nil, fmt.Errorf("foo %s %w", reason, err)
	}
	
	f, err := os.Open(path) or return errHdlr("couldn't open file", err)
	defer f.Close() or return errHdl("", fmt.Errorf("couldn't close file"))
	result, err := io.ReadAll(f) or return errHdlr("couldn't read from file " + path, err)
	return result, nil
}
复制代码

antiguo:

func Foo(path string) ([]byte, error) {
	f, err := os.Open(path)
  	if err != nil {
    		return nil, fmt.Errorf("foo %s %w", "couldn't open file", err)
  	}
  	result, err := io.ReadAll(f)
  	if err != nil {
    		return nil, fmt.Errorf("foo %s %w", "couldn't read from file " + path, err)
  	}
  	err = f.Close()
  	if err != nil {
    		return nil, fmt.Errorf("foo %s %w", "couldn't close the file " + path, err)
  	}
  	return result, nil
}
复制代码

Este es un ejemplo muy simple, pero ya podemos ver los beneficios. Un programador que está leyendo código puede incluso enfocarse en la izquierda e ignorar el manejo de errores.

Después de formatear el código con gofmt, también es más hermoso.

El siguiente ejemplo:

f, err := os.Open(path)      or return errHdlr("couldn't open file", err)
defer f.Close()              or return errHdl("", fmt.Errorf("couldn't close file"))
result, err := io.ReadAll(f) or return errHdlr("couldn't read from file " + path, err)
复制代码

Muy bien.

Resumir

En esta nueva propuesta, el autor se encuentra en la etapa de solicitud de comentarios. Principalmente promueve varias ideas como la palabra clave o y las variables se pueden pasar a la función de la derecha (también compartí una propuesta de funciones y expresiones de la izquierda hace algún tiempo).

El propósito del autor es hacerlo lo más conveniente posible, y no escribir el if err != nil del que todos se han quejado en el pasado, para lograr una mayor concisión.

¿Qué te parece esta propuesta? Bienvenido a intercambiar y discutir en el área de comentarios.

El artículo se actualiza continuamente, puede leerlo en WeChat buscando [Brain Fried Fish], este artículo se ha incluido en GitHub github.com/eddycjy/blo… Si está aprendiendo el idioma Go, puede ver el mapa de aprendizaje Go y ruta Bienvenido a Star para instarlo a actualizar.

Ir serie de libros

Lee mas

Supongo que te gusta

Origin juejin.im/post/7119709660445147150
Recomendado
Clasificación