将参数传递给HandlerFunc

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

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 (
	&quot;github.com/ajstarks/svgo&quot;
	&quot;log&quot;
	&quot;net/http&quot;
)

func svgWeb(w http.ResponseWriter, req *http.Request) {
	w.Header().Set(&quot;Content-Type&quot;, &quot;image/svg+xml&quot;)

	xpts := []int{1, 200, 5}
	ypts := []int{200, 400, 300}
	s := svg.New(w)
	s.Start(500, 500)
	s.Line(5, 10, 400, 400, &quot;stroke:black&quot;)
	s.Polyline(xpts, ypts, &quot;stroke:black&quot;)
	s.End()
}

//// Main Program function
//////////////////////////////

func main() {

	xpts := []int{}
	ypts := []int{}

	for i := 0; i &lt; 100; i++ {
		xpts = append(xpts, i)
		xpts = append(ypts, i+5)
	}

	http.Handle(&quot;/economy&quot;, http.HandlerFunc(svgWeb))
	err := http.ListenAndServe(&quot;:2003&quot;, nil)
	if err != nil {
		log.Fatal(&quot;ListenAndServe:&quot;, 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实例,它还可以包含其他处理程序,并且可以更新以影响其处理程序的输出。

满足Handler接口

如@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(&quot;Content-Type&quot;, &quot;image/svg+xml&quot;)

    s := svg.New(w)
    s.Start(500, 500)
    s.Line(5, 10, 400, 400, &quot;stroke:black&quot;)
    s.Polyline(m.Xpts, m.Ypts, &quot;stroke:black&quot;)
    s.End()
}

Then in your main:

<!-- language: lang-go -->

manager := new(SvgManager)

for i := 0; i &lt; 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(&quot;/economy&quot;, 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(&quot;/economy&quot;, manager)

答案2

得分: 1

你应该将函数定义在main函数内部,作为一个匿名函数。这样,它可以引用局部变量xptsypts(该函数将成为一个闭包)。

英文:

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

huangapple
  • 本文由 发表于 2012年4月9日 05:23:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/10066643.html
匿名

发表评论

匿名网友

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

确定