3 ms·
I don't really use an interactive debugger with Go that often. I prefer error wrapping and logging. That having been said, I've found that it is often best to d
by kbolino 2y ago
I don't really use an interactive debugger with Go that often. I prefer error wrapping and logging. That having been said, I've found that it is often best to disentangle reflection and business logic by converting to an intermediate representation. For example, I wrote a library that takes a struct pointer and populates its target with values taken from environment variables, using field tags like `env:"FOO"`. The first version did at least have useful error messages, e.g.
reading environment into struct: struct field Foo: as int32: strconv.ParseInt: parsing "a": invalid syntax
However, it wasn't very extensible, because you had to read through a lot of boilerplate to figure out where to put new features. I also bet debugging this through an interactive debugger would have been quite a headache, though I never had to do that. So I rewrote it and split it into two parts: a reflection-based part which returned details about the extracted fields and their tags, then a (nearly) reflection-free part which took those details and parsed the corresponding environment variables then injected the values into the fields. The intermediate representation is usually hidden behind a simple interface, but can be examined when needed, and prints nicely for debugging.