Yaml: Mejor error al descomponer en valor no puntero

Creado en 24 nov. 2016  ·  5Comentarios  ·  Fuente: go-yaml/yaml

Recientemente me encontré con un problema que hizo que me tirara del pelo un poco, por lo que creo que el problema principal es que se produce un pánico inesperado con un error oscuro en lugar de prevenir el error o devolver un error detallado. Este fue un gran problema de usabilidad ya que solo encontré la fuente del problema después de prueba y error para los campos YAML y struct y luego revisé la fuente de go-yaml. La fuente de este error podría ser un error del desarrollador o si se están analizando archivos YAML del usuario que no son válidos. Personalmente me encontré con esto porque creía que una estructura de biblioteca era analizable en YAML cuando en realidad no lo era, mientras que las otras estructuras de la biblioteca sí lo eran.

El problema es que cuando hay un campo en el YAML que no corresponde a un campo en la estructura, todos los métodos reflect.Set causarán pánico inmediatamente. Para evitar esto, puede hacer reflect.CanSet para verificar el campo de antemano. Esto podría usarse para dos formas de recuperación de errores:

1) Ignore el problema en silencio y no establezca el campo en absoluto, ya que no corresponde al campo de estructura adecuado

2) No desarme el YAML y simplemente devuelva un error

Código de ejemplo y stacktrace

package main

import (
    "fmt"

    "gopkg.in/yaml.v2"
)

const problemYaml = `
name: GO_BUILDER
`

type config struct {
    Name string
}

func main() {
    var c = config{}
    _ = yaml.Unmarshal([]byte(problemYaml), c)
    fmt.Println("I will not reach here, and can't handle the error for invalid YAML input.")
}
panic: reflect: reflect.Value.SetString using unaddressable value [recovered]
    panic: reflect: reflect.Value.SetString using unaddressable value

goroutine 1 [running]:
panic(0x4df780, 0xc42000e610)
    /usr/lib/go/src/runtime/panic.go:500 +0x1a1
gopkg.in/yaml%2ev2.handleErr(0xc42003ff00)
    /home/joey/.go/src/gopkg.in/yaml.v2/yaml.go:153 +0xe7
panic(0x4df780, 0xc42000e610)
    /usr/lib/go/src/runtime/panic.go:458 +0x243
reflect.flag.mustBeAssignable(0x98)
    /usr/lib/go/src/reflect/value.go:228 +0x102
reflect.Value.SetString(0x4df780, 0xc42000e550, 0x98, 0xc42000e590, 0xa)
    /usr/lib/go/src/reflect/value.go:1511 +0x2b
gopkg.in/yaml%2ev2.(*decoder).scalar(0xc4200121c0, 0xc42005c240, 0x4df780, 0xc42000e550, 0x98, 0x4df780)
    /home/joey/.go/src/gopkg.in/yaml.v2/decode.go:371 +0x1187
gopkg.in/yaml%2ev2.(*decoder).unmarshal(0xc4200121c0, 0xc42005c240, 0x4df780, 0xc42000e550, 0x98, 0xc42000e550)
    /home/joey/.go/src/gopkg.in/yaml.v2/decode.go:290 +0x122
gopkg.in/yaml%2ev2.(*decoder).mappingStruct(0xc4200121c0, 0xc42005c180, 0x4ea360, 0xc42000e550, 0x99, 0xc42002c028)
    /home/joey/.go/src/gopkg.in/yaml.v2/decode.go:635 +0x641
gopkg.in/yaml%2ev2.(*decoder).mapping(0xc4200121c0, 0xc42005c180, 0x4ea360, 0xc42000e550, 0x99, 0x4ea360)
    /home/joey/.go/src/gopkg.in/yaml.v2/decode.go:513 +0xaad
gopkg.in/yaml%2ev2.(*decoder).unmarshal(0xc4200121c0, 0xc42005c180, 0x4ea360, 0xc42000e550, 0x99, 0xc42005c180)
    /home/joey/.go/src/gopkg.in/yaml.v2/decode.go:292 +0x216
gopkg.in/yaml%2ev2.(*decoder).document(0xc4200121c0, 0xc42005c120, 0x4ea360, 0xc42000e550, 0x99, 0x44a210)
    /home/joey/.go/src/gopkg.in/yaml.v2/decode.go:304 +0x84
gopkg.in/yaml%2ev2.(*decoder).unmarshal(0xc4200121c0, 0xc42005c120, 0x4ea360, 0xc42000e550, 0x99, 0x10)
    /home/joey/.go/src/gopkg.in/yaml.v2/decode.go:280 +0x268
gopkg.in/yaml%2ev2.Unmarshal(0xc42000a3c0, 0x12, 0x20, 0x4ea360, 0xc42000e550, 0x0, 0x0)
    /home/joey/.go/src/gopkg.in/yaml.v2/yaml.go:90 +0x2ba
main.main()
    /home/joey/code/gum/error.go:15 +0xcc
exit status 2

Comentario más útil

Recibí el mismo error hasta que pasé la estructura por dirección "& c"
_ = yaml.Unmarshal ([] byte (problemYaml), & c)

Todos 5 comentarios

El mismo problema aqui. Sería bueno que si algo falla, lo obtenga a través del valor de retorno err .

Sería bueno saber qué campo está arrojando este error, simplemente obtuve lo mismo y no sé por qué, necesito usar la depuración, creo

Recibí el mismo error hasta que pasé la estructura por dirección "& c"
_ = yaml.Unmarshal ([] byte (problemYaml), & c)

Sí, la situación es de pánico porque es un error de codificación. El yaml proporcionado es completamente válido y la estructura también está bien. Pero simplemente no hay forma posible de que la lógica funcione cuando c no se proporciona como puntero.

Sin embargo, mantendré este problema abierto para mejorar el mensaje de error.

¿Algún progreso en la mejora del mensaje de error? @niemeyer

¿Fue útil esta página
0 / 5 - 0 calificaciones