Reputation: 4482
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)
}
}
Upvotes: 1
Views: 773
Reputation: 92637
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:
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:
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
func (m *SvgManager) ServeHTTP(w http.ResponseWriter, req *http.Request) {
...
manager := new(SvgManager)
http.Handle("/economy", manager)
Upvotes: 2
Reputation: 122519
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).
Upvotes: 1