Как напечатать байтовый член struct [] в виде строки - PullRequest
0 голосов
/ 23 января 2020

У меня следующая структура:

type foo struct {
   number int
   data []byte
}

И я хочу напечатать объект из структуры "красивым" способом. Что я делаю:

obj := foo{
    number: 1,
    data: []byte("json"),
}
fmt.Printf("Obj: %+v", obj)

Что я получаю:

Obj: {number:1 data:[106 115 111 110]}

Что я хочу:

Obj: {number:1 data:"json"}

Могу ли я сделать это без реализации Stringer или использования отражения?

Ответы [ 2 ]

0 голосов
/ 23 января 2020

Возможно, реализация Stringer лучше, но вот пример реализации (слегка) fmt интерфейса Formatter:

package main

import (
    "fmt"
)

type foo struct {
    number int
    data   []byte
}

func (x foo) Format(f fmt.State, c rune) {
    var s string
    switch c {
    case 's', 'v':
        if f.Flag('+') {
            s = fmt.Sprintf("{number:%d data:%q}", x.number, x.data)
        } else {
            s = fmt.Sprintf("{%d %q}", x.number, x.data)
        }
    default:
        s = "(bad formatting verb)"
    }
    f.Write([]byte(s))
}

func main() {
    o1 := foo{number: 1, data: []byte("json")}
    o2 := foo{number: 1, data: []byte("\001with\u2038unicode")}
    o3 := foo{number: 42, data: nil}
    fmt.Printf("o1: %+v\n", o1)
    fmt.Printf("o2: %v\n", o2)
    fmt.Printf("o3: %#v\n", o3)
}

Объект o3 здесь, чтобы показать, насколько отсутствует: обработка нуля, обработка других глаголов и флагов форматирования и так далее. (Я не коснулся ширины и точности!)

ссылка на игровую площадку

0 голосов
/ 23 января 2020

(Отказ от ответственности: я думаю, что лучше использовать% q для отладочной печати, но это зависит от ваших потребностей. Я добавляю эту альтернативу только потому, что интерфейс GoStringer представляет собой интересный трюк) .

Другим выходом за пределы% q является обертывание байта [] типом, реализующим интерфейс GoStringer, который будет вызываться для форматирования %#v. Допустим, у нас есть:

type PrintableBuffer []byte

func (b PrintableBuffer) GoString() string {
    return string(b)
}

Теперь мы определяем структуру:

type foo struct {
    number int
    Data   PrintableBuffer
}

(чтобы этот трюк работал, нужно, чтобы член был опубликован c: /)

А потом:

func main() {
    obj := foo{
        number: 1,
        Data:   PrintableBuffer("json"),
    }
    fmt.Printf("Obj: %#v", obj)
}

Распечатает:

Obj: main.foo{number:1, Data:json}
...