golang http обработчик сервера и проблема с указателем - PullRequest
0 голосов
/ 21 марта 2020

Я немного растерялся с go -программами, http-сервером, обработчиками и указателями.

  1. Я создал 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
}

1 Ответ

0 голосов
/ 21 марта 2020

Это оказалось довольно просто, я закрыл глаза на это задание здесь

return &MyServer{
    pid:            s,
    Port:           currentPort,
    requestHandler: rh,
}

Что привело к еще одной копии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...