В Go, может ли JSON маршалинг четко определенного типа когда-либо терпеть неудачу?

С учетом следующего кода:

package main

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

type Employee struct {
    Id int "json:id"
}

func main() {
    b, err := json.Marshal(&Employee{Id: 2})
    if err != nil {
        log.Fatal("Couldn't marshal the Employee")
    }

    fmt.Println(string(b))
}

Может ли проверка ошибки быть надежно проигнорирована с помощью заполнителя _, так как структура Employee определена корректно. Теоретически это никогда не должно терпеть неудачу, поэтому возникает вопрос, является ли хорошей практикой игнорировать этот тип ошибок и немного сэкономить на этом типе проверки ошибок шаблонов?

Игнорирование будет выглядеть так:

package main

import (
    "encoding/json"
    "fmt"
)

type Employee struct {
    Id int "json:id"
}

func main() {
    b, _ := json.Marshal(&Employee{Id: 2})
    fmt.Println(string(b))
}

Ответ 1

Обработка ошибок и переход:

Правильная обработка ошибок - необходимое требование хорошего программного обеспечения.


Обычно ваш код не будет работать. но если пользователь добавляет этот метод MarshalJSON к вашему типу, он терпит неудачу:

func (t *Employee) MarshalJSON() ([]byte, error) {
    if t.Id == 2 {
        return nil, fmt.Errorf("Forbiden Id = %d", t.Id)
    }
    data := []byte(fmt.Sprintf(`{"Id":%d}`, t.Id))
    return data, nil
}

Этот код компилируется, но с ошибкой назначается только для Id == 2 (Игровая площадка Go):

package main

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

type Employee struct {
    Id int "json:id"
}

func main() {
    b, err := json.Marshal(&Employee{Id: 2})
    if err != nil {
        log.Fatal("Couldn't marshal the Employee", err)
    }

    fmt.Println(string(b))
}

func (t *Employee) MarshalJSON() ([]byte, error) {
    if t.Id == 2 {
        return nil, fmt.Errorf("Forbiden Id = %d", t.Id)
    }
    data := []byte(fmt.Sprintf(`{"Id":%d}`, t.Id))
    return data, nil
}

Также этот код компилируется, но не работает (The Go Playground):

package main

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

type Employee struct {
    Id int "json:id"
}

func main() {
    b, err := json.Marshal(&Employee{Id: 2})
    if err != nil {
        log.Fatal("Couldn't marshal the Employee")
    }

    fmt.Println(string(b))
}

func (t Employee) MarshalJSON() ([]byte, error) {
    data := []byte(fmt.Sprint(t))
    return data, nil
}

Ответ 2

Вы всегда можете написать свои собственные пакеты "обертки", чтобы составить поведение, которое в противном случае могло бы быть шаблоном. Например, если у вас установлена ​​система ведения журнала, вы можете создать небольшой пакет, который выглядит следующим образом:

package json
import (
  "encoding/json"
  "log"
)
func TryMarshal(v interface{}) []byte {
  b, err := json.Marshal(v)
  if err != nil {
    log.Println(err)
    return nil
  }
  return b
}