为什么我不能在Go的一个单独的包中编写HTTP响应?

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

Why can't I write an HTTP response from a seperate package in Go?

问题

我正在使用httprouter来设置一个API端点,但是在正确输出响应方面遇到了一些问题。

我的主要文件如下:

package main

import (
	"fmt"
	"github.com/julienschmidt/httprouter"
	"infrastructure/routing"
	"log"
	"net/http"
)

func testPrint(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
	fmt.Fprint(w, "Test output.")
}

func main() {

	fmt.Printf("\n************************************\n")
	fmt.Printf("MySite Application Server\n")
	fmt.Printf("Version: %s", "Unversioned Development Build\n")
	fmt.Printf("************************************\n\n")

	router := httprouter.New()

	//////Records//////
	router.GET("/test", testPrint)
	router.GET("/records", routing.RecordList)
	router.GET("/records/id/:id", routing.RecordGetById)
	router.GET("/records/name/:name", routing.RecordGetByName)
	router.GET("/records/search/*search-string", routing.RecordSearch)
	router.HEAD("/records/:id", routing.RecordGetExists)
	router.POST("/records", routing.RecordCreate)
	router.PATCH("/records", routing.RecordUpdate)
	router.PUT("/records", routing.RecordUpsert)
	router.DELETE("/records/:id", routing.RecordDelete)
	router.DELETE("/records/:id/undelete", routing.RecordUndelete)
	router.DELETE("/records/:id/purge", routing.RecordPurge)

	fmt.Printf("Listening on port 8080...\n")
	log.Fatal(http.ListenAndServe(":8080", router))

}

大部分处理函数位于infrastructure/routing中,但问题就出在这里。目前路由的代码如下:

package routing

import (
	"fmt"
	"github.com/julienschmidt/httprouter"
	"net/http"
)

func RecordList(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	//返回记录列表。
	fmt.Fprint(w, "Returned a list of records.")
}

func RecordGetById(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
	//返回指定ID的记录。
	w.Write([]byte("Returned a record by its ID."))
}

func RecordGetByName(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
	//返回名称字段中包含指定字符串的记录。
	w.Write([]byte("Returned a record by its name."))
}

func RecordSearch(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
	//根据提供的搜索词进行全文搜索。
	w.Write([]byte("Search results."))
}

func RecordGetExists(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
	//返回记录是否存在。
	w.Write([]byte("Returns whether a record exists. Should usually return 200 or 404."))
}

func RecordCreate(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
	//从请求体中的JSON数据创建新记录。
	w.Write([]byte("Creates new records."))
}

func RecordUpdate(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
	//使用请求体中的JSON数据更新记录。
	w.Write([]byte("Updates existing records."))
}

func RecordUpsert(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
	//使用请求体中的JSON数据更新现有记录并创建新记录。
	w.Write([]byte("Upserts records."))
}

func RecordDelete(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
	//将具有指定ID的记录标记为已删除。
	w.Write([]byte("Marks records as deleted."))
}

func RecordUndelete(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
	//将具有指定ID的记录标记为未删除。
	w.Write([]byte("Marks deleted records as undeleted."))
}

func RecordPurge(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
	//永久删除具有指定ID的记录。
	w.Write([]byte("Permanently deletes record with given ID."))
}

当我向localhost:8080/test发出请求时,它调用了主包中的处理函数并打印了"Test output."。但是,任何其他定义的URL都返回200 OK状态码和一个空的(0字节)响应体,而不是预期的文本。

我相当确定这与传递的ResponseWriter对象有关,但我无法弄清楚为什么它对同一包中的一个函数起作用,而对不同包中的另一个函数却不起作用,尽管这两个函数都有一个传递的写入器的副本。我尝试了几种不同的写入方式,包括fmt.FPrintfio.WriteStringw.Write,但都没有成功。

英文:

I'm using httprouter to set up an API endpoint, but I'm having some trouble getting it to output a response correctly.

My main file as it stands:

package main
import (
"fmt"
"github.com/julienschmidt/httprouter"
"infrastructure/routing"
"log"
"net/http"
)
func testPrint(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
fmt.Fprint(w, "Test output.")
}
func main() {
fmt.Printf("\n************************************\n")
fmt.Printf("MySite Application Server\n")
fmt.Printf("Version: %s", "Unversioned Development Build\n")
fmt.Printf("************************************\n\n")
router := httprouter.New()
//////Records//////
router.GET("/test", testPrint)
router.GET("/records", routing.RecordList)
router.GET("/records/id/:id", routing.RecordGetById)
router.GET("/records/name/:name", routing.RecordGetByName)
router.GET("/records/search/*search-string", routing.RecordSearch)
router.HEAD("/records/:id", routing.RecordGetExists)
router.POST("/records", routing.RecordCreate)
router.PATCH("/records", routing.RecordUpdate)
router.PUT("/records", routing.RecordUpsert)
router.DELETE("/records/:id", routing.RecordDelete)
router.DELETE("/records/:id/undelete", routing.RecordUndelete)
router.DELETE("/records/:id/purge", routing.RecordPurge)
fmt.Printf("Listening on port 8080...\n")
log.Fatal(http.ListenAndServe(":8080", router))
}

Most of the handler functions are located in infrastructure/routing, but this is where the problem starts. The code for routing is currently:

package routing
import (
"fmt"
"github.com/julienschmidt/httprouter"
"net/http"
)
func RecordList(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
//Returns a list of records.
fmt.Fprint(w, "Returned a list of records.")
}
func RecordGetById(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
//Return a record with the specified ID.
w.Write([]byte("Returned a record by its ID."))
}
func RecordGetByName(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
//Returns a record with the specified string in the name field.
w.Write([]byte("Returned a record by its name."))
}
func RecordSearch(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
//Full text search for the search term provided.
w.Write([]byte("Search results."))
}
func RecordGetExists(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
//Returns whether a record exists.
w.Write([]byte("Returns whether a record exists. Should usually return 200 or 404."))
}
func RecordCreate(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
//Creates new records from JSON data in request body.
w.Write([]byte("Creates new records."))
}
func RecordUpdate(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
//Updates records using JSON data in request body.
w.Write([]byte("Updates existing records."))
}
func RecordUpsert(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
//Updates existing records and creates new ones using JSON data in request body.
w.Write([]byte("Upserts records."))
}
func RecordDelete(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
//Marks the record with the specified ID as deleted.
w.Write([]byte("Marks records as deleted."))
}
func RecordUndelete(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
//Marks the record with the specified ID as undeleted.
w.Write([]byte("Marks deleted records as undeleted."))
}
func RecordPurge(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
//Permanently deletes the record with the specified ID.
w.Write([]byte("Permanently deletes record with given ID."))
}

When I make a request to localhost:8080/test, it calls the handler function in the main package and prints "Test output.". But any of the other defined URLs return a 200 OK status code and an empty (0 bytes) response body instead of the expected text.

I'm fairly sure this is something to do with the ResponseWriter object being passed through but I can't figure out why it works for one function in the same package but not another function in a different package, even though both functions have a copy of the writer passed through. I've tried a few different ways of writing including fmt.FPrintf, io.WriteString, and w.Write, to no avail.

答案1

得分: 1

好的,以下是翻译好的内容:

嗯,事实证明,当我构建代码时,由于某种原因,它没有更新对象文件。我已经使用LiteIDE一段时间了,这是第一次单独点击所有相关包的“构建”按钮没有起作用。

我进行了清理,然后使用了“全部构建”,现在它可以正常工作了。

英文:

Well, as it turns out when I was building my code for whatever reason it wasn't keeping the object files updated. I've been using LiteIDE for a while and this is the first time clicking Build on all relevant packages individually hasn't worked.

I cleaned it and then used Build All, now it works.

huangapple
  • 本文由 发表于 2015年9月16日 23:01:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/32612262.html
匿名

发表评论

匿名网友

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

确定