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
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
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
Comentario más útil
Recibí el mismo error hasta que pasé la estructura por dirección "& c"
_ = yaml.Unmarshal ([] byte (problemYaml), & c)