I am building a simple API to communicate with a light SQL database.
I created this function, that gets all hosts from the DB table.
As I understand, my function should take a pointer to the DB and return me http.HandlerFunc.
func (h HostController) GetAllHosts(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var host entities.Host
var hosts []entities.Host
var errorMessage entities.Error
rows, err := db.Query("SELECT * FROM hosts WHERE hosts = ?", host)
if err != nil {
errorMessage.Message = "Error: Get all hosts"
utils.SendError(w, http.StatusInternalServerError, errorMessage)
return
}
defer rows.Close()
for rows.Next() {
err := rows.Scan(&host.ID, &host.Uuid, &host.Name, &host.IPAddress)
if err != nil {
errorMessage.Message = "Error: (Get all hosts) Can't scan rows"
utils.SendError(w, http.StatusInternalServerError, errorMessage)
return
}
hosts = append(hosts, host)
}
////If hosts slice is empty -> no data in database
if len(hosts) == 0 {
errorMessage.Message = "No found hosts in database"
utils.SendError(w, http.StatusInternalServerError, errorMessage)
return
}
//Convert containers content to JSON representation
w.Header().Set("Content-Type", "application/json")
utils.SendSuccess(w, hosts)
}
}
Now, Until here everything should be good, but I don't know how to implement this on main.go build layout:
.
├── controllers
│ └── hostcontroller.go
│
└── main.go
and this is how I am trying to implement it on the main.go
package main
import (
"examProg/config"
"examProg/controllers"
"fmt"
"log"
"net/http"
"github.com/gorilla/mux"
_ "github.com/mattn/go-sqlite3"
)
func main() {
db := config.GetDB() //Establishing connection to DBase
{
router := mux.NewRouter()
router.Handle("/host", controllers.HostController.GetAllHosts(db))
fmt.Println("Server is running at port: 2030")
log.Println("Server Running OK | Port: 2030")
log.Fatal(http.ListenAndServe(":2030", router))
}
}
I don't understand how to implement the http.HandlerFunc 🙃
The expression controllers.HostController.GetAllHosts
is a method expression. The result of a method expression is a function
that, in addition to the method
's argument's, takes an instance of the receiver's type as its first argument.
Hence the "not enough arguments in call ..." error.
To illustrate:
f := controllers.HostController.GetAllHosts
fmt.Println(reflect.TypeOf(f))
// output: func(controllers.HostController, *sql.DB)
So, to make the code compile, you need to pass an instance of controllers.HostController
to the call, i.e.
controllers.HostController.GetAllHosts(controllers.HostController{}, db)
As you can see, it ain't pretty. Method expressions have their use, I'm sure, but I haven't encountered them much. What I see most often instead, is the use of method values.
h := controllers.HostController{}
router.Handle("/host", h.GetAllHosts(db))