Я немного растерялся с go -программами, http-сервером, обработчиками и указателями.
- Я создал http-сервер, который принимает любой запрос на любом пути, я запускаю его в отдельная подпрограмма, поэтому основной поток не блокируется
// main thread
// I want to bind to random port and read port later
listener, err := net.Listen("tcp", ":0")
rh := requestHandler{} // look at point 2)
s := &http.Server{
Handler: rh,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
go func() {
err := s.Serve(listener)
...
}()
rh
- это интерфейс обработчика, поэтому я создал структуру, следующую за интерфейсом
type requestHandler struct {
values []string
}
func (rh requestHandler) ServeHTTP(w http.ResponseWriter, givenRequest *http.Request) {
log.Println("DEBUG : handling request", givenRequest.Method, givenRequest.URL, givenRequest.RequestURI)
log.Println("DEBUG : headers", givenRequest.Header)
for _, value := range rh.values { // <----- values are always empty
}
}
позволяет добавить некоторые значения в обработчик
// main thread
rh.values = append(rh.values, "one)
, очевидно, это не работает, поскольку сервер копирует обработчик, а переменная rh
из основного потока имеет указатель, отличный от s.Handler
, но это все в порядке.
Что я не понимаю, так это то, что rh
в func (rh requestHandler) ServeHTTP(w http.ResponseWriter, givenRequest *http.Request)
имеет другой указатель, чем s.Handler
.
как я могу передать что-либо в requestHandler.values из основного потока, чтобы эти значения можно было прочитать в функции обратного вызова? Я пытался использовать каналы, но не могу получить доступ к указателю / ссылке вправо rh
. Это потому, что каждый запрос также появляется в новой подпрограмме, а обработчик также копируется?
пример кода
type MyServer struct {
Port int
pid *http.Server
requestHandler requestHandler
}
func (s *MyServer) addValue(value string) {
s.requestHandler.values = append(s.requestHandler.values, value)
}
func InitializeServer() *MyServer {
rh := requestHandler{}
listener := bindToNextFreePort()
s := &http.Server{
Handler: rh,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
startServer(s, listener)
currentPort := getTcpPort(listener)
log.Println("My Server Initialized on ", currentPort)
return &MyServer{
pid: s,
Port: currentPort,
requestHandler: rh,
}
}
func startServer(s *http.Server, listener net.Listener) {
go func() {
log.Println("starting Mock Server")
err := s.Serve(listener)
}()
}
type requestHandler struct {
values []string
}
func (rh requestHandler) ServeHTTP(w http.ResponseWriter, givenRequest *http.Request) {
log.Println("DEBUG : handling request", givenRequest.Method, givenRequest.URL, givenRequest.RequestURI)
log.Println("DEBUG : headers", givenRequest.Header)
for key, value := range rh.values {
}
}
func bindToNextFreePort() net.Listener {
listener, err := net.Listen("tcp", ":0")
if err != nil {
panic(err)
}
return listener
}