英文:
How to add call Handlefunc outside main in Golang (Http)
问题
我目前已经编写了一个可工作的 Golang 脚本,但是为了连贯性,如果我想添加另一个页面,我需要能够从一个单独的函数中调用 http.HandleFunc
。
我知道这不是一个好的做法,但我对 Golang 还不熟悉。
我想要能够从一个单独的函数中调用主函数中的 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request)
部分。
以下是代码:
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)
}
每当我尝试其他示例时,似乎在模板方面遇到了困难。
英文:
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.
答案1
得分: 1
你正在使用http.HandleFunc
函数:
http.HandleFunc("/", someFunction)
所以正如@JimB评论的那样,为什么不将其提取为一个函数?
func someFunction(w http.ResponseWriter, r *http.Request) {
...
}
func main() {
http.HandleFunc("/", someFunction)
...
}
然而,阅读你的函数,你还在进行一系列的数据库调用和模板执行,所以我认为你在函数内部可能无法使用它们。在这种情况下,你可能希望创建一个具有与HandleFunc签名匹配的方法或返回HandleFunc的结构体。
参考这个Stack Overflow回答。
Mat Ryer在How I write Http Services after Eight Years中概述了这种技术("Handlers hang off the server")。
英文:
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.
答案2
得分: -1
你可以尝试使用Fiber库来解决这个问题。在Fiber中,你可以使用app := fiber.New()
来创建你的端点。如果你将这个app变量作为指针传递给其他函数,并在该函数内部创建一个你想要的端点,最后在主函数中启动这个app来提供服务。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论