El principal criterio del diseño de go es: fácil de entender, simple es la sintaxis similar a C es bastante sencillo de entender se refiere a cualquier declaración es evidente, no contiene cosas ocultas en el diseño del programa de gestión de errores también poner en práctica esta idea. Sabemos que existe en el lenguaje C, devolviendo -1 o NULL para indicar el tipo de mensaje de error, pero para los usuarios que no ven la documentación de la API, el valor de retorno no sabemos exactamente lo que significa, por ejemplo: return 0 es el éxito o el fracaso, y Go define un tipo llamado el error de expresar explícitamente errores. Cuando está en uso, por la comparación nula variable de error devuelto para determinar si la operación se ha realizado correctamente. Por ejemplo os.Open función abre el archivo volverá un fracaso de la variable not nil
func Open (name string) (file * File, err error)
He aquí un ejemplo llamando os.Open abrir un archivo si se produce un error, se llamará a la log.Fatal mostrar un mensaje de error::
f, err := os.Open("filename.ext")
if err != nil {
log.Fatal(err)
}
Similar a la os.Open función, el paquete estándar de todos los posibles errores de la API devolverá una variable de error para facilitar el manejo de errores, esta sección Tipo de error detalle diseño, y discutir cómo desarrollar aplicaciones Web para una mejor error de identificador.
error
es un tipo de interfaz, con esta definición:
type error interface {
Error() string
}
error
es una continuación / paquete integrado tipo de interfaz, podemos / orden interna para encontrar la definición adecuada. Y lo que tenemos es utilizado una gran cantidad de error interno dentro de los errores de paquetes de paquetes siguiente estructura de ejecución errorString privado
// errorString is a trivial implementation of error.
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
usted puede errors.New
poner una cadena en errorString, con el fin de conseguir una reunión el objeto de error de interfaz cuya implementación interna es el siguiente:
// Nueva devuelve un error que da formato como el texto dado
func New(text string) error {
return &errorString{text}
}
El siguiente ejemplo muestra cómo utilizar errors.New
:
func Sqrt(f float64) (float64, error) {
if f < 0 {
return 0, errors.New("math: square root of negative number")
}
// implementation
}
En el siguiente ejemplo, que llamamos el Sqrt al pasar un número negativo, y entonces obtenemos el objeto de error es no-nil, nil en comparación con este objeto, el resultado es verdadero, por lo fmt.Println (paquete fmt cuando se trata de llamadas de error el método de error) se llama a un error de salida, mira el siguiente código de ejemplo para llamar:
f, err := Sqrt(-1)
if err != nil {
fmt.Println(err)
}
A través de la descripción anterior sabemos que el error es una interfaz, por lo que en la realización de su paquete, mediante la definición de la estructura implementa esta interfaz, podemos darnos cuenta de sus definiciones de error, consulte el paquete de Json Ejemplo:
type SyntaxError struct {
msg string // error description
Offset int64 // where the error occurred
}
func (e * SyntaxError) Error() string {return e.msg}
Error campo Desplazamiento en el tiempo de la llamada no se imprimirá, pero podemos obtener a través de un tipo de error de aserción de tipo, entonces usted puede imprimir un mensaje de error apropiado, consulte los siguientes ejemplos:
if err := dec.Decode(&val); err != nil {
if serr, ok := err.(*json.SyntaxError); ok {
line, col := findLine(f, serr.Offset)
return fmt.Errorf("%s:%d:%d: %v", f.Name(), line, col, err)
}
return err
}
Tenga en cuenta que, la función devuelve un error personalizado, el valor devuelto se establece en recomendar el tipo de error, en lugar de un tipo de error personalizados, nota en particular no debe ser previamente declarar tipos de error personalizados de variables. Por ejemplo:
func Decode() *SyntaxError {
// error , which may lead to the upper caller err! = nil judgment is always true.
var err * SyntaxError // pre- declare error variable
if an error condition {
err = & SyntaxError {}
}
return err // error , err always equal non- nil, causes the upper caller err! = nil judgment is always true
}
Cause see http://golang.org/doc/faq#nil_error
El ejemplo anterior muestra cómo un simple tipo de error personalizado. Pero si necesitamos error más sofisticado manejarlo? En este punto, tenemos que hacer referencia al enfoque de red paquete:
package net
type Error interface {
error
Timeout() bool // Is the error a timeout?
Temporary() bool // Is the error temporary?
}
Ponga la llamada a través de la afirmación de err tipo no es net.Error, para refinar el manejo de errores, como el siguiente ejemplo, si se produce un error temporal en la red, se va a dormir 1 segundo de reintento:
if nerr, ok := err.(net.Error); ok && nerr.Temporary() {
time.Sleep(1e9)
continue
}
if err != nil {
log.Fatal(err)
}
Ve en el manejo de errores en el uso de la C comprobar el valor devuelto de manera similar, en lugar de la mayoría de los otros idiomas principales utilizados de maneras inesperadas, lo que causó un código escrito en una gran desventaja: el manejo de errores de código de redundancia, para este tipo de situación es que detectamos función para reducir la reutilización de código similar.
Mira el siguiente código de ejemplo:
func init() {
http.HandleFunc("/view", viewRecord)
}
func viewRecord(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
record := new(Record)
if err := datastore.Get(c, key, record); err != nil {
http.Error(w, err.Error(), 500)
return
}
if err := viewTemplate.Execute(w, record); err != nil {
http.Error(w, err.Error(), 500)
}
}
El ejemplo anterior muestra una plantilla para obtener los datos y la llamada se ha detectado un error cuando se produce un error, llamar a una función de procesamiento unificado http.Error , devuelve al cliente 500 código de error y mostrar los datos de error correspondientes. Pero cuando más y más HandleFunc unió, para que el código de lógica de manejo de errores será cada vez más, de hecho, podemos personalizar el router para reducir el código (realización de las ideas se puede hacer referencia al Capítulo III del HTTP detallado).
type appHandler func(http.ResponseWriter, *http.Request) error
func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if err := fn(w, r); err != nil {
http.Error(w, err.Error(), 500)
}
}
Arriba hemos definido un enrutador personalizado, y luego podemos adoptar el siguiente enfoque de función de registro:
func init() {
http.Handle("/view", appHandler(viewRecord))
}
Cuando así lo solicite /view
cuando podemos llegar a ser código de procesamiento como lógica, y la primera aplicación ha sido comparado con una mucho más simple..
func viewRecord(w http.ResponseWriter, r *http.Request) error {
c := appengine.NewContext(r)
key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
record := new(Record)
if err := datastore.Get(c, key, record); err != nil {
return err
}
return viewTemplate.Execute(w, record)
}
El ejemplo anterior gestión de errores cuando los errores se devuelven al usuario 500 código de error, y luego imprimir el código de error correspondiente, de hecho, podemos poner esta definición los mensajes de error más amigables al depurar también es conveniente un problema de posicionamiento, podemos volver personalizada tipos de errores:
type appError struct {
Error error
Message string
Code int
}
Así que nuestro router personalizado puede ser cambiado de la siguiente manera:
type appHandler func(http.ResponseWriter, *http.Request) *appError
func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if e := fn(w, r); e != nil { // e is *appError, not os.Error.
c := appengine.NewContext(r)
c.Errorf("%v", e.Error)
http.Error(w, e.Message, e.Code)
}
}
Tal error personalizado después de modificar nuestra lógica se puede cambiar de la siguiente manera:
func viewRecord(w http.ResponseWriter, r *http.Request) *appError {
c := appengine.NewContext(r)
key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
record := new(Record)
if err := datastore.Get(c, key, record); err != nil {
return &appError{err, "Record not found", 404}
}
if err := viewTemplate.Execute(w, record); err != nil {
return &appError{err, "Can't display record", 500}
}
return nil
}
Como puede observarse, en nuestra opinión, cuando se puede visitar de acuerdo a las diferentes situaciones de los diferentes códigos de error y mensajes de error, aunque esta primera versión del código y la cantidad es casi, pero este espectáculo es el error más obvio, el mensaje de error le pide más amigable , la escalabilidad es también mejor que el primero.
En la programación, la tolerancia a fallos es una parte muy importante de la obra, en el Go es logrado a través de la gestión de errores, el error aunque sólo una interfaz, pero puede tener muchas variaciones, pero podemos de acuerdo a sus necesidades para lograr un tratamiento diferente introducir último tratamiento de errores esquema, esperamos que en la forma de diseñar mejores programas en el manejo de errores Web para traer algunas ideas.
- Directory
- Previous section: Error handling, debugging and testing
- Next section: Debugging by using GDB