http函数Golang的附加参数

I am trying to pass string to handler in given example.

package main
import (
"fmt"
"net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
     fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}

func main() {
     http.HandleFunc("/", handler)
     http.ListenAndServe(":8080", nil)
}

Here is what i tried but it throws an error as it expects regular number of arguments:

package main
import (
"fmt"
"net/http"
)

func handler(w http.ResponseWriter, r *http.Request, s *string) {
     fmt.Fprintf(w, "Hi there, I love %s!", *s)
}

func main() {
     files := "bar"
     http.HandleFunc("/", handler(&files))
     http.ListenAndServe(":8080", nil)
}

I'm a little unclear on what you're trying to do, but based off what you said, why not try to encapsulate the data you want to pass in like this:

package main
import (
    "fmt"
    "net/http"
)

type FilesHandler struct {
    Files string
}

func (fh *FilesHandler) handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there, I love %s!", fh.Files)
}

func main() {
    myFilesHandler := &FilesHandler{Files: "bar"}
    http.HandleFunc("/", myFilesHandler.handler)
    http.ListenAndServe(":8080", nil)
}

This provides a little more granular control of what you make available to your Handler.

There are lots of options here, you could:

  • Use a closure to set state for the enclosed handler
  • Use a method on a struct for the handler, and set global state there
  • Use the request context to store a value, then get it out
  • Use a package global to store the value
  • Write your own router with a new signature (not as complex as it sounds, but probably not a good idea)
  • Write a helper function to do things like extract params from the url

It depends what s is really - is it a constant, is it based on some state, does it belong in a separate package?

One of ways is to store data in global variable:

package main

import (
    "fmt"
    "net/http"
)

var replies map[string]string

func handler1(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()
    question := r.FormValue("question")
    var answer string
    var ok bool
    if answer, ok = replies[question]; !ok {
        answer = "I have no answer for this"
    }
    fmt.Fprintf(w, "Hi there, I love %s! My answer is: %s", question, answer)
}

func main() {
    //files := "bar"
    replies = map[string]string{
        "UK": "London",
        "FR": "Paris",
    }
    http.HandleFunc("/", handler1)
    http.ListenAndServe(":8080", nil)
}

Here for brevity I've commented out files and put data as is into the map. You may read the file and put them there.

Usage with CURL:

$ curl -X POST 127.0.0.1:8080/ -d "question=FR"
Hi there, I love FR! My answer is: Paris

$ curl -X POST 127.0.0.1:8080/ -d "question=US"
Hi there, I love US! My answer is: I have no answer for this