To read any response you must turn wire-format labels back into a dotted name. Today you decode a QNAME by walking its length-prefixed labels until the zero terminator, and report how many bytes you consumed.
Decode a length-prefixed name back to a dotted string and its byte length.
Decoding reverses the encoder: read a length byte, take that many characters as
a label, and repeat until you hit the zero terminator. Joining the labels with
dots rebuilds www.example.com. The one subtlety is that callers need to know
how many bytes the name occupied, because in a real message the type and class
fields (and the next record) come right after it - so return the consumed length
alongside the string.
Count carefully: the seventeen bytes of www.example.com include the final 00,
so the consumed length is 17, and example.com consumes 13. This
consumed-length discipline is what lets a parser advance cleanly from one field to
the next, and you will lean on it constantly once records start stacking up.
Today’s decoder assumes every name is spelled out in full; chapter three adds the
compression pointers that let a name borrow bytes from earlier in the message.
func decodeName(b []byte, off int) (string, int) {var labels []stringi := offfor b[i] != 0 { // stop at the zero root labeln := int(b[i]); i++labels = append(labels, string(b[i:i+n]))i += n}return strings.Join(labels, "."), (i + 1) - off // +1 for the terminator}