Удалить одно поле структуры из байтового среза - PullRequest
0 голосов
/ 07 августа 2020

Мне интересно, как изменить байты в моем методе записи.

Байты, которые нужно удалить, составляют трассировку стека типа из службы регистрации, которая является частью type errWithStackTrace struct, поэтому я можно получить это значение, используя json .Unmarshal в байтовом срезе, как показано ниже. Если эта трассировка стека присутствует, я бы хотел, чтобы все было записано, кроме нее.

    func (w *customWriter) Write(p []byte) (int, error) {
        e := loggedEvent{}
        if err := json.Unmarshal(p, &e); err != nil {
            return len(p), nil
        }
        if e.ErrWithStack.Stacktrace != nil {
            // modify p to remove e.ErrWithStack.Stacktrace bytes?
            return os.Stdout(p)
        }
        return os.Stdout(p)
    }

Я попытался преобразовать e.ErrWithStack.Stacktrace в байты, а затем заменить его, но он все равно записывает все событие.

    if e.ErrWithStack.Stacktrace != nil {
        reqBytes := new(bytes.Buffer)
        json.NewEncoder(reqBytes).Encode(e.ErrWithStack.Stacktrace)
        res := bytes.Replace(p, reqBytes.Bytes(), []byte(""), 1)
        return os.Stdout.Write(res)
    }

1 Ответ

1 голос
/ 07 августа 2020

return os.Stdout(p) здесь не имеет смысла, но в любом случае основная проблема заключается в том, что если на входе json и вы его декодировали, вы не знаете, что это за исходный ввод. Нет простого способа найти строку для удаления, так как то, что у вас уже декодировано.

Конечно, вы можете написать свой собственный json парсер и найти и удалите предмет таким образом. Это единственный способ сохранить остаток кодировки как есть.

Более простой вариант - удалить ошибку и перекодировать. Достаточно того, что вы не показали здесь, что трудно понять, будет ли это нормально, но я взял ваш пример процедуры, сделал ее компилируемой и построил для нее небольшую тестовую среду, но вот она (и ссылка на Go площадка ):

package main

import (
    "encoding/json"
    "fmt"
    "os"
)

type loggedEvent struct {
    Thing1            string  `json:"thing1"`
    ErrWithStackTrace *string `json:"err,omitempty"`
    Thing2            string  `json:"thing2"`
}

var inputs [][]byte = [][]byte{
    []byte(`{"thing1":"a string","err":"here is a stack trace","thing2":"another string"}`),
    []byte(`{"thing1":"a\u0020string","err":"here\u0020is\u0020a\u0020stack\u0020trace","thing2":"u-encoded"}`),
    []byte(`{"thing1":"more strings","thing2":"no error this time"}`),
}

type customWriter struct{}

func (w *customWriter) Write(p []byte) (int, error) {
    e := loggedEvent{}
    if err := json.Unmarshal(p, &e); err != nil {
        fmt.Printf("note: unable to unmarshal %q\n", p)
        return len(p), nil
    }
    if e.ErrWithStackTrace != nil {
        // fmt.Printf("note: removing ErrWithStackTrace part\n")
        e.ErrWithStackTrace = nil
    }
    s, err := json.Marshal(e)
    if err != nil {
        fmt.Printf("help, failed to re-marshal e=%v: err=%v\n", e, err)
        return 0, err
    }
    s = append(s, '\n')
    return os.Stdout.Write(s)
}

func main() {
    w := &customWriter{}
    for _, inp := range inputs {
        ret, err := w.Write(inp)
        if err != nil {
            fmt.Printf("ret = %d, err = %v\n", ret, err)
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...