package main import ( "database/sql" "encoding/json" "fmt" "io/ioutil" "net/http" "strconv" "time" ) //Go Best practices: https://github.com/golovers/effective-go type Item struct { Id int32 `json:"id"` Name int32 `json:"name"` ValueCents int32 `json:"valueCents"` PurchaseCostCents int32 `json:"purchasedCostCents"` Aquired time.Time `json:"aquired"` Description string `json:"description"` Notes string `json:"notes"` SoldForCents int32 `json:"soldForCents"` SoldTo string `json:"soldTo"` Category Category `json:"category"` Subcategory Subcategory `json:"subcategory"` } func main() { http.HandleFunc("/categories", categories) http.HandleFunc("/category", category) err := http.ListenAndServe(":8080", nil) if err != nil { panic(err) } } func categories(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": getCategories(w, r) default: w.WriteHeader(http.StatusMethodNotAllowed) w.Write([]byte("Method not allowed")) } } func category(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": getCategory(w, r) case "POST": insertCategory(w, r) case "DELETE": deleteCategory(w, r) default: w.WriteHeader(http.StatusMethodNotAllowed) w.Write([]byte("Method not allowed")) } } func getCategory(w http.ResponseWriter, r *http.Request) { id := r.URL.Query().Get("id") value, err := strconv.ParseInt(id, 0, 64) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } db := getSQLConnection() defer db.Close() var category Category if err := db.QueryRow("SELECT * FROM category WHERE category_id = $1;", value).Scan(&category.Id, &category.Name); err != nil { if err == sql.ErrNoRows { w.Write([]byte("No rows found")) return } w.Write([]byte(err.Error())) return } jsonBytes, err := json.Marshal(&category) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } w.WriteHeader(http.StatusOK) w.Write(jsonBytes) } func deleteCategory(w http.ResponseWriter, r *http.Request) { id := r.URL.Query().Get("id") value, err := strconv.ParseInt(id, 0, 64) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } db := getSQLConnection() defer db.Close() _, err = db.Exec("DELETE FROM category WHERE category_id = $1;", value) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } w.WriteHeader(http.StatusOK) w.Write([]byte(fmt.Sprintf("Deleted category '%d'.", value))) } func getCategories(w http.ResponseWriter, r *http.Request) { categories := getAllCategories() jsonBytes, err := json.Marshal(categories) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("Failed to get a list of categories.")) return } w.WriteHeader(http.StatusOK) w.Write(jsonBytes) } func insertCategory(w http.ResponseWriter, r *http.Request) { ct := r.Header.Get("content-type") if ct != "application/json" { w.WriteHeader(http.StatusUnsupportedMediaType) w.Write([]byte(fmt.Sprintf("Unsupported media type '%s'", ct))) return } bodyBytes, err := ioutil.ReadAll(r.Body) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte("Failed to parse request body")) return } defer r.Body.Close() var category Category err = json.Unmarshal(bodyBytes, &category) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte("Failed to unmarshal JSON")) return } db := getSQLConnection() defer db.Close() id := 0 err = db.QueryRow("INSERT INTO category (category_name) VALUES ($1) RETURNING category_id;", category.Name).Scan(&id) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } w.WriteHeader(http.StatusOK) w.Write([]byte(fmt.Sprintf("New Record: %d", id))) }