Здесь обратная задача, то есть, не в json, а обратно. При этом в условиях задано, что структура неизвестная.
map[string]interface{} — это просто общий интерфейс объекта json. Естественно, что в него декодируется любой объект из json строки.
И да, конечно, переменную типа map[string]interface{} можно создать в коде и потом её кодировать в json, и это было бы решением прямой задачи. Собственно, его код я и спрашивал. Просто интересно, чем конкретно оно лучше. Те решения, что я встречал (через map[string]interface{}), лучшими бы я не назвал.
Если я правильно понял, то Вы предлагаете использовать дополнительный приватный атрибут типа
toJson func() (data []byte, err error)
И именно в него положить всю логику преобразования в json.
При этом для каждого отображения нужно иметь свою функцию. Теперь вопрос: а что будет в тех функциях? типа такого:
Если как по мне, то читабельности и разделения кода становится на порядок меньше, хотя как показывают замеры скорости, это будет быстрее.
Или имелось в виду совсем другое решение?
Про скорость и бенчмарки. (в ответ TonyLorencio, Sly_tom_cat и, кончено, всем, кому интересно).
Главный вопрос тут, конечно, про целесообразность использования gob, и дополнительного кодирования/декодирования, поэтому давайте рассмотрим именно этот момент.
Вообще, решение конечно более архитектурное, направленное на разделение кода, чтобы при сливании git веток меньше приходилось править конфликты, которые бы были неизбежны, если бы всё решение было внутри функции MarshalJSON.
Итак, давайте сделаем тоже самое, но без использования gob, а с прямым заполнением структуры. В коде есть закомментированный текст — о нём будет далее.
Тест создаёт список из элементов и потом получает json строку. Результаты: BenchmarkRun0-8 20000 68701 ns/op
BenchmarkRun1-8 200000 7177 ns/op
То есть, использование gob даёт замедление в 10 раз. Да, это несколько больше, чем ожидалось.
Но это простые типы данных: int64 и string. А что будет, если будет что-то посложнее? Давайте добавим список литературы.
Код LInks
type Link struct {
Title string
Description string
Rate float64
}
type Links []Link
type Book struct {
Id int64
Title string
Description string
Partner2Title string
Price int64
PromoPrice int64
PromoDescription string
Partner1Price int64
Partner2Price int64
Links Links
UpdatedAt time.Time
CreatedAt time.Time
view BookView
}
type SiteBookView struct {
Id int64 `json:"sku"`
Title string `json:"title"`
Description string `json:"description"`
Price int64 `json:"price"`
Links Links `json:"links"`
}
//к остальным также добавим Links с каким-то json всевдонимом
Пусть всегда будет по списку литературу в 100 позиций. Результаты уже не столь плачевны:
BenchmarkRun0-8 3000 493611 ns/op
BenchmarkRun1-8 5000 322898 ns/op
Замедление уже составляет 52%. При более сложных данных может быть и меньше.
Если вам нужно выводить до 100 элементов, при этом их структура достаточно сложная, то замедление будет не столь критичным. Если это тонны информации, и каждая миллисекунда на счету, то, возможно, то данное решение может быть не очень эффективным.
Да, это плата за разделение кода, уменьшение риска конфликтов при слиянии git веток, наглядность моделей. Возможно, этого всего можно добиться и без gob, или с ним, но другим, более эффективным решением. Если найду — обязательно поделюсь.
map[string]interface{} — это просто общий интерфейс объекта json. Естественно, что в него декодируется любой объект из json строки.
И да, конечно, переменную типа map[string]interface{} можно создать в коде и потом её кодировать в json, и это было бы решением прямой задачи. Собственно, его код я и спрашивал. Просто интересно, чем конкретно оно лучше. Те решения, что я встречал (через map[string]interface{}), лучшими бы я не назвал.
И именно в него положить всю логику преобразования в json.
При этом для каждого отображения нужно иметь свою функцию. Теперь вопрос: а что будет в тех функциях? типа такого:
Если как по мне, то читабельности и разделения кода становится на порядок меньше, хотя как показывают замеры скорости, это будет быстрее.
Или имелось в виду совсем другое решение?
Главный вопрос тут, конечно, про целесообразность использования gob, и дополнительного кодирования/декодирования, поэтому давайте рассмотрим именно этот момент.
Вообще, решение конечно более архитектурное, направленное на разделение кода, чтобы при сливании git веток меньше приходилось править конфликты, которые бы были неизбежны, если бы всё решение было внутри функции MarshalJSON.
Итак, давайте сделаем тоже самое, но без использования gob, а с прямым заполнением структуры. В коде есть закомментированный текст — о нём будет далее.
Тест создаёт список из элементов и потом получает json строку. Результаты:
BenchmarkRun0-8 20000 68701 ns/op
BenchmarkRun1-8 200000 7177 ns/op
То есть, использование gob даёт замедление в 10 раз. Да, это несколько больше, чем ожидалось.
Но это простые типы данных: int64 и string. А что будет, если будет что-то посложнее? Давайте добавим список литературы.
Пусть всегда будет по списку литературу в 100 позиций. Результаты уже не столь плачевны:
BenchmarkRun0-8 3000 493611 ns/op
BenchmarkRun1-8 5000 322898 ns/op
Замедление уже составляет 52%. При более сложных данных может быть и меньше.
Если вам нужно выводить до 100 элементов, при этом их структура достаточно сложная, то замедление будет не столь критичным. Если это тонны информации, и каждая миллисекунда на счету, то, возможно, то данное решение может быть не очень эффективным.
Да, это плата за разделение кода, уменьшение риска конфликтов при слиянии git веток, наглядность моделей. Возможно, этого всего можно добиться и без gob, или с ним, но другим, более эффективным решением. Если найду — обязательно поделюсь.