附加到结构片

I'm having issues initializing a slice of struct and adding to it.

I'm trying to model the below JSON so I created struct called Error for individual errors and a slice of Errors to hold them. I know I can do errSlice := []Err{} but that won't show the JSON tag.

{
  "errors": [
    {
      "status": "422",
      "source": { "pointer": "/data/attributes/firstName" },
      "title":  "Invalid Attribute",
      "detail": "First name must contain at least three characters."
    }
  ]
}

My attempt:

package main

import (
    "encoding/json"
    "net/http"
)

// ErrSlice is a slice of type Err
type ErrSlice struct {
    Errors []Err `json:"errors"`
}

// Err is an error
type Err struct {
    Status string `json:"status"`
    Source Source `json:"source"`
    Title  string `json:"title"`
    Detail string `json:"detail"`
}

// Source is struct of error source
type Source struct {
    Pointer string `json:"pointer"`
}

func main() {
    http.HandleFunc("/", foo)
    http.ListenAndServe(":9001", nil)
}

func foo(w http.ResponseWriter, r *http.Request) {

    errSlice := ErrSlice{}

    // New error
    err1 := Err{
        Status: "422",
        Source: Source{
            Pointer: "/data/attributes/firstName",
        },
        Title:  "Invalid Attribute",
        Detail: "First name must contain at least three characters.",
    }

    // Append err1 to errSlice
    errSlice = append(errSlice, err1) // error: "first argument to append must be slice"

    // Marshall errSlice
    jsonErrSlice, _ := json.Marshal(errSlice)

    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusUnprocessableEntity)
    w.Write(jsonErrSlice)
}

Thanks for your time!

I figured out a way to get the required format but I'm sure there is a cleaner way to implement this:

package main

import (
    "encoding/json"
    "net/http"
)

// Err struct are individual errors
type Err struct {
    Status string `json:"status"`
    Source Source `json:"source"`
    Title  string `json:"title"`
    Detail string `json:"detail"`
}

// Source is a struct for source inside an error
type Source struct {
    Pointer string `json:"pointer"`
}

// JSONErrors stores the json error data
type JSONErrors struct {
    Errors []Err `json:"errors"`
}

func main() {
    http.HandleFunc("/", foo)
    http.ListenAndServe(":9001", nil)
}

func foo(w http.ResponseWriter, r *http.Request) {

    // Create slice of errors
    errSlice := []Err{}

    // New error
    err1 := Err{
        Status: "422",
        Source: Source{
            Pointer: "/data/attributes/firstName",
        },
        Title:  "Invalid Attribute",
        Detail: "First name must contain at least three characters.",
    }

    // Append to error slice
    errSlice = append(errSlice, err1)

    // Assign errSlice to JSONErrors
    jsonErrRes := JSONErrors{Errors: errSlice}

    // Marshall errSlice
    jsonErrSlice, _ := json.Marshal(jsonErrRes)

    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusUnprocessableEntity)
    w.Write(jsonErrSlice)

    // Results:
    // {
    //  "errors": [
    //      {
    //          "status": "422",
    //          "source": {
    //              "pointer": "/data/attributes/firstName"
    //          },
    //          "title": "Invalid Attribute",
    //          "detail": "First name must contain at least three characters."
    //      }
    //  ]
    // }
}