How to add call Handlefunc outside main in Golang (Http)

huangapple go评论91阅读模式
英文:

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来提供服务。

Fiber的GitHub仓库

英文:

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

huangapple
  • 本文由 发表于 2022年1月28日 22:55:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/70895725.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定