1

I currently built a working golang script, but for continuity if I wanted to add another page I'd need to be able to call the http.HandleFunc from a seperate function.

I know this isn't good practice, but I am new to Golang.

I'd like to be able to call the http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) part of the main function from a separate function,

Below is the code:

package main

import (
    "database/sql"
    "fmt"
    "html/template"
    "net/http"
    "strconv"

    "github.com/rs/xid"

    _ "github.com/go-sql-driver/mysql"
)

func main() {

    tmpl := template.Must(template.ParseFiles("Add-Vehicle.html"))

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if r.Method != http.MethodPost {
            tmpl.Execute(w, nil)
            return
        }

        db, err := sql.Open("mysql", "root:WgFl3f8218!@tcp(127.0.0.1:3306)/my_db")

        if err != nil {
            fmt.Println("Connection Failed.")
            panic(err.Error())
        }

        defer db.Close()

        id := xid.New()
        var brand_ = r.FormValue("select")
        var model_ = r.FormValue("select-1")

        year_, err := strconv.ParseInt(r.FormValue("year")[0:], 10, 64)
        if err != nil {
            fmt.Println(err)
        }

        mileage_, err := strconv.ParseInt(r.FormValue("text")[0:], 10, 64)
        if err != nil {
            fmt.Println(err)
        }

        dayrate_, err := strconv.ParseInt(r.FormValue("dayrate")[0:], 10, 64)
        if err != nil {
            fmt.Println(err)
        }

        insert, err := db.Query("INSERT INTO vehicle(id, date, brand, model, mileage, manufactured, rented, dayrate) VALUES ( ?, NOW(), ?, ?, ?, ?, 0, ?)", id.String(), brand_, model_, mileage_, year_, dayrate_)
        if err != nil {
            panic(err.Error())
        } 
        defer insert.Close()

        tmpl.Execute(w, struct {
            Success bool
            Brand   string
            Model   string
            Year    int64
            Mileage int64
            Dayrate int64
        }{true, brand_, model_, year_, mileage_, dayrate_})
    })

    http.Handle("/css/", http.StripPrefix("/css", http.FileServer(http.Dir("./css"))))
    http.Handle("/js/", http.StripPrefix("/js", http.FileServer(http.Dir("./js"))))
    http.Handle("/images/", http.StripPrefix("/images", http.FileServer(http.Dir("./images"))))
    http.ListenAndServe(":9090", nil)
}

Whenever I've tried other examples, I seem to struggle with the template side of things.

2 Answers2

1

You’re using http.HandleFunc

http.HandleFunc("/", someFunction)

so as @JimB commented, why not extract that out as a function?

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

func main() {
    http.HandleFunc("/", someFunction)
...
}

However reading your function, you’re also doing a bunch of DB calls and template execution so I think you’ll run into not having those available inside the your function. In that case you may want to create a struct with a method on it that matches the HandleFunc signature or that returns a HandleFunc.

See this SO Answer

Also Mat Ryer outlines this technique (“Handlers hang off the server”) in How I write Http Services after Eight Years.

AlexMe
  • 36
  • 1
  • 2
-1

You can try fiber library for this issue. In fiber you can create your end points with app variable app := fiber.New(). If you pass this app variable to other functions with pointer and create an end point inside of the that function as you would like. Finally start to serve this app on main function.

Fiber's GitHub repository