学习Go:如何使用http.HandlerFunc?

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

Learning Go: How to use http.HandlerFunc?

问题

尝试学习Go语言

我的测试项目

我正在构建一个与轻量级SQL数据库通信的简单API。我创建了这个函数,用于从数据库表中获取所有主机。根据我的理解,我的函数应该接受一个指向数据库的指针,并返回一个http.HandlerFunc。

func (h HostController) GetAllHosts(db *sql.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// 函数体代码
	}
}

到目前为止,一切都应该没问题,但是我不知道如何在main.go中实现它。

目录结构如下:

.
├── controllers
│   └── hostcontroller.go
│       
└── main.go

以下是我在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() // 建立与数据库的连接

	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))
}

我不明白如何实现http.HandlerFunc

英文:

Trying To Learn Go

My Test Project

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 🙃

答案1

得分: 1

表达式controllers.HostController.GetAllHosts是一个方法表达式。方法表达式的结果是一个函数,除了方法的参数之外,还将接收者类型的实例作为其第一个参数。

因此会出现“调用中参数不足”的错误。

举个例子:

f := controllers.HostController.GetAllHosts
fmt.Println(reflect.TypeOf(f))
// 输出:func(controllers.HostController, *sql.DB)

所以,为了使代码编译通过,你需要将controllers.HostController的实例传递给调用,即:

controllers.HostController.GetAllHosts(controllers.HostController{}, db)

正如你所见,这并不美观。方法表达式肯定有其用途,但我并没有经常遇到它们。我经常看到的是使用方法值

h := controllers.HostController{}
router.Handle("/host", h.GetAllHosts(db))
英文:

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))

huangapple
  • 本文由 发表于 2022年9月3日 14:02:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/73590015.html
匿名

发表评论

匿名网友

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

确定