I've been learning to code and recently finished a server-client project in javascript. In that server (Node.js) I wrote myself a "responder" function that I called dozens of times throughout the program:
function sendResponse(req, res, err, response, redirect) {
if (err) {
res.status(err.status)
return res.json(err.message || err.error)
}
if (response) {
res.status(response.status)
return res.json(response.response || response.message)
}
if (redirect) {
return res.redirect(redirect)
}
res.status(500)
return res.json({message: err.err || "Unknown server error", user: req.userObj.email || null})
}
I'm now trying to write a similar API-serving backend in Go. While of course you can pass nil to functions, what I can't figure out is how to allow any of those parameters to be "dynamic" - perhaps that is the point of a statically typed language? In javascript, the response parameter could be an object with string keys & values, or it could have nested objects with additional data to send back to the client. In Go, I could take a map as a parameter, but I'd have to define it in advance as a string:string map. If I wanted to nest a map, I'd also have to define the mappings of the nested map.
This is the closest I've gotten in Go:
func responder(w http.ResponseWriter, m map[string]string, s int) {
w.WriteHeader(s)
w.Header().Set("Content-Type", "application/json; charset=utf-8")
if m != nil {
r := createJson(m)
w.Write(r)
return
}
w.Write([]byte("Good job"))
return
}
func createJson(m map[string]string) ([]byte) {
j, err := json.Marshal(m)
if err != nil {
fmt.Println(err)
return nil
}
return j
}
But I'm starting to get the feeling I am just thinking about how to do things in statically typed languages incorrectly.
Edit: Is this a job for pointers? Could I use a pointer to a map that may or may not contain nested maps?
you can make a struct with a type field inside the struct and act according to the type using switch case.
you can use interface{} here as shown below
func responder(w http.ResponseWriter, m interface{}, s int) {
w.WriteHeader(s)
w.Header().Set("Content-Type", "application/json; charset=utf-8")
if m != nil {
r := createJson(m)
w.Write(r)
return
}
w.Write([]byte("Good job"))
return
}
func createJson(m interface{}) ([]byte) {
j, err := json.Marshal(m)
if err != nil {
fmt.Println(err)
return nil
}
return j
}