英文:
Pass arguments into HandlerFunc
问题
我正在尝试使用svgo包在svg文件上绘制点,并在Web浏览器中显示。从查看net/http
文档,我不知道如何将参数传递给我的svgWeb
函数。
下面的示例编译并在我的Web浏览器中显示一个三角形和一条线,但我真正想做的是使用Polyline方法绘制xpts和ypts。如何传递适当的参数或重新构造此示例以完成此任务?
package main
import (
"github.com/ajstarks/svgo"
"log"
"net/http"
)
func svgWeb(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "image/svg+xml")
xpts := []int{1, 200, 5}
ypts := []int{200, 400, 300}
s := svg.New(w)
s.Start(500, 500)
s.Line(5, 10, 400, 400, "stroke:black")
s.Polyline(xpts, ypts, "stroke:black")
s.End()
}
//// Main Program function
//////////////////////////////
func main() {
xpts := []int{}
ypts := []
for i := 0; i < 100; i++ {
xpts = append(xpts, i)
xpts = append(ypts, i+5)
}
http.Handle("/economy", http.HandlerFunc(svgWeb))
err := http.ListenAndServe(":2003", nil)
if err != nil {
log.Fatal("ListenAndServe:", err)
}
}
英文:
I am trying to use the svgo package to plot points on an svg file and display that using the web browser. From looking at the net/http
documetation, I don't know how I could pass arguments into my svgWeb
function.
The example below compiles and displays a triangle and a line in my web-browser, but what I would really like to do is plot xpts and ypts using the Polyline method. How can I pass the appropriate arguments or restructure this example to accomplish that task?
package main
import (
"github.com/ajstarks/svgo"
"log"
"net/http"
)
func svgWeb(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "image/svg+xml")
xpts := []int{1, 200, 5}
ypts := []int{200, 400, 300}
s := svg.New(w)
s.Start(500, 500)
s.Line(5, 10, 400, 400, "stroke:black")
s.Polyline(xpts, ypts, "stroke:black")
s.End()
}
//// Main Program function
//////////////////////////////
func main() {
xpts := []int{}
ypts := []int{}
for i := 0; i < 100; i++ {
xpts = append(xpts, i)
xpts = append(ypts, i+5)
}
http.Handle("/economy", http.HandlerFunc(svgWeb))
err := http.ListenAndServe(":2003", nil)
if err != nil {
log.Fatal("ListenAndServe:", err)
}
}
答案1
得分: 2
如果您的参数是由客户端提供的,则应通过http.Request
将它们传递给您的处理程序。
但是,如果您要做的是通过应用程序中的其他函数生成这些值而不是由客户端请求提供的点来驱动您的svgWeb
处理程序,那么一种方法是将处理程序结构化为一个结构并使用成员属性。
该结构可能如下所示:
type SvgManager struct {
Xpts, Ypts []int
}
func (m *SvgManager) SvgWeb(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "image/svg+xml")
s := svg.New(w)
s.Start(500, 500)
s.Line(5, 10, 400, 400, "stroke:black")
s.Polyline(m.Xpts, m.Ypts, "stroke:black")
s.End()
}
然后在您的主函数中:
manager := new(SvgManager)
for i := 0; i < 100; i++ {
manager.Xpts = append(manager.Xpts, i)
manager.Ypts = append(manager.Ypts, i+5)
}
// 我只是为了使SO显示的宽度更短而进行了此赋值。
// 可以直接放在http.Handle()中
handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
manager.SvgWeb(w, req)
})
http.Handle("/economy", handler)
现在您有一个SvgManager实例,它还可以包含其他处理程序,并且可以更新以影响其处理程序的输出。
如@Atom在评论中提到的,您可以通过将方法重命名为ServeHTTP来完全避免闭包和包装器。这将满足Handler接口。
func (m *SvgManager) ServeHTTP(w http.ResponseWriter, req *http.Request) {
...
manager := new(SvgManager)
http.Handle("/economy", manager)
英文:
If your arguments are meant to be supplied by the client, then they should be passed to your handler via the http.Request
.
But if what you are trying to do is to drive your svgWeb
handler by points that are not supplied by the client request, but rather by some other functions in your application generating these values internally, then one way would be to structure your handler into a struct and use member attributes.
The struct may look like this:
<!-- language: lang-go -->
type SvgManager struct {
Xpts, Ypts []int
}
func (m *SvgManager) SvgWeb(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "image/svg+xml")
s := svg.New(w)
s.Start(500, 500)
s.Line(5, 10, 400, 400, "stroke:black")
s.Polyline(m.Xpts, m.Ypts, "stroke:black")
s.End()
}
Then in your main:
<!-- language: lang-go -->
manager := new(SvgManager)
for i := 0; i < 100; i++ {
manager.Xpts = append(manager.Xpts, i)
manager.Ypts = append(manager.Ypts, i+5)
}
// I only did this assignment to make the SO display shorter in width.
// Could have put it directly in the http.Handle()
handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
manager.SvgWeb(w, req)
})
http.Handle("/economy", handler)
Now you have an SvgManager instance that could contain other handlers as well, and can be updated to affect the output of their handlers.
Satisfying the Handler interface
As mentioned by @Atom in the comments, you could completely avoid the closure and the wrapper by simply renaming your method to ServeHTTP. This would satisfy the Handler interface
<!-- language: lang-go -->
func (m *SvgManager) ServeHTTP(w http.ResponseWriter, req *http.Request) {
...
manager := new(SvgManager)
http.Handle("/economy", manager)
答案2
得分: 1
你应该将函数定义在main
函数内部,作为一个匿名函数。这样,它可以引用局部变量xpts
和ypts
(该函数将成为一个闭包)。
英文:
You should define your function inside main
as an anonymous function. This way, it can refer to the local variables xpts
and ypts
(the function will be a closure).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论