I am writing a Write a controller for a golang http app, the controller is for Users. The model/data handling for the users has the following functions
func NewUserService(db *sql.DB) *UserService { func (u *UserService) GetUserExists(email string) (bool, error) { func (u *UserService) GetUserById(id ID) (*User, error) { func userBuilder(email string, name string) *User { func (u *UserService) GetOrCreateUserByEmail(email string, name string) (*User, error) { func (u *UserService) GetUserByEmail(email string) (*User, error) { func (u *UserService) CreateUser(user *User) error {
for the controller, I have some simple stubbed out methods, I want these to be completed using these methods from the models. The model methods under the Repo member of the UserResource struct:
//the controller:
package resources
import ( "database/sql" "net/http" "scheduleme/frame" "scheduleme/models"
"github.com/go-chi/render"
)
// User data model const UserContextKey contextKey = "user"
// type Repo struct { // UserService *UserService // EventService *EventService // AuthService *AuthService // }
func NewUserResource(db *sql.DB, repo *models.Repo) *UserResource { return &UserResource{db: db} }
type UserResource struct { db *sql.DB Repo *models.Repo }
func (u *Resources) ListUsers(w http.ResponseWriter, r *http.Request) { w.Write([]byte("users list of stuff..")) }
func (u *Resources) CreateUser(w http.ResponseWriter, r *http.Request) { w.Write([]byte("users create")) }
func (u *Resources) GetUser(w http.ResponseWriter, r *http.Request) { ri := frame.RouteInfoFromContext(r.Context()) //convert user to json render.JSON(w, r, ri.User)
}
func (u *Resources) UpdateUser(w http.ResponseWriter, r *http.Request) { w.Write([]byte("user update")) }
func (u *Resources) DeleteUser(w http.ResponseWriter, r *http.Request) { w.Write([]byte("user delete")) }
Sure, based on your UserService methods, I have filled in the UserResource controller methods.
Here is the updated version of your UserResource controller.
package resources
import (
"database/sql"
"net/http"
"scheduleme/frame"
"scheduleme/models"
"github.com/go-chi/chi"
"github.com/go-chi/render"
)
const UserContextKey contextKey = "user"
func NewUserResource(db *sql.DB, repo *models.Repo) *UserResource {
return &UserResource{db: db, Repo: repo}
}
type UserResource struct {
db *sql.DB
Repo *models.Repo
}
func (u *UserResource) ListUsers(w http.ResponseWriter, r *http.Request) {
users, err := u.Repo.UserService.All()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
render.JSON(w, r, users)
}
func (u *UserResource) CreateUser(w http.ResponseWriter, r *http.Request) {
var user models.User
if err := render.DecodeJSON(r.Body, &user); err != nil {
render.Render(w, r, ErrInvalidRequest(err))
return
}
err := u.Repo.UserService.CreateUser(&user)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
render.Status(r, http.StatusCreated)
render.JSON(w, r, &user)
}
func (u *UserResource) GetUser(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
user, err := u.Repo.UserService.GetUserById(id)
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
render.JSON(w, r, user)
}
func (u *UserResource) UpdateUser(w http.ResponseWriter, r *http.Request) {
var user models.User
if err := render.DecodeJSONHandlerFunc(r.Body, &user); err != nil {
http.Error(w, "Bad Request.", http.StatusBadRequest)
return
}
err := u.Repo.UserService.UpdateUser(&user)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
render.JSON(w, r, &user)
}
func (u *UserResource) DeleteUser(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
err := u.Repo.UserService.DeleteUser(id)
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
render.NoContent(w, r)
}
Note: Make sure that your UserService struct has the All(), UpdateUser() and DeleteUser() methods. As those methods were not mentioned but they are commonly used in User services, so I included them in the UserController assuming that your UserService struct also contains these functions.
I have used render.DecodeJSON() from go-chi/render package to read the body of the incoming request, please do not forget to import this package if it is not already there in your code.
Also, I've parsed "id" from the RouteInfo context and passed it to the UserService methods. Here, the "id" is expected to be passed in as a part of the URL. If you plan to request "id" in a different way, please modify this part of the implementation accordingly.