2013-07-26 3 views
2

간단한 http 서버 작성 이외의 절대 초보자를 골란으로 지정. 나는 비동기 프로세스 작성 가능성에 대해 연구 중이다. 원하는 경우 수행 방법에 대한 간단한 샘플을 제공하십시오.Golang : 비동기 http 서버의 공유 통신

HTTP 요청 'a'가 입력되면이 요청의 POST 페이로드를 기반으로 작업이 시작됩니다 (게시물 또는 URL에 고유 식별자가있는 경우) . 'a'에 의해 시작된 비동기 프로세스는 요청 'a'가 아직 열려있는 동안 원래의 고유 식별자 (요청 'b')로 동일한 서버에 응답합니다. 요청 'b'응답을 기반으로 'a'를 요청하려면 해당 응답을 다시 전달하고 싶습니다.

+0

내가 응용 프로그램을 코딩을 요청 아니에요, 난 그냥이 공유 메모리 또는 채널을 통해 달성 될 수 있는지 여부에 하회하고있어, 및 채널을 통해 고유 한 식별자를 기반으로 수행되는 방법 내가 이해하는 한, 간단한 예제는 약 5-10 줄 이어야만합니까? – kwolfe

+0

이게 당신이 원하는거야? 요청은 클라이언트에서 서버로 이루어집니다. 그런 다음 서버는 요청 b를 클라이언트에 다시 보냅니다. 또는 고객이 두 번째 요청을 발행합니까? – andybalholm

+0

채널은이를 수행하는 훌륭한 방법입니다. 더 많은 방향을 제시하기 전에 더 많은 세부 정보가 필요합니다. –

답변

6

채널을 사용하여이 작업을 수행 할 수도 있지만 이 경우 더 쉽기 때문에 뮤텍스 (mutex)로 보호되는 해시 (지도)를 선호합니다.

하는 당신에게 아이디어를 제공하고 가야 :

package main 

import (
    "fmt" 
    "net/http" 
    "sync" 
) 

type state struct { 
    *sync.Mutex // inherits locking methods 
    Vals map[string]string // map ids to values 
} 

var State = &state{&sync.Mutex{}, map[string]string{}} 

func get(rw http.ResponseWriter, req *http.Request) { 
    State.Lock() 
    defer State.Unlock() // ensure the lock is removed after leaving the the function 
    id := req.URL.Query().Get("id") // if you need other types, take a look at strconv package 
    val := State.Vals[id] 
    delete(State.Vals, id) 
    rw.Write([]byte("got: " + val)) 
} 

func post(rw http.ResponseWriter, req *http.Request) { 
    State.Lock() 
    defer State.Unlock() 
    id := req.FormValue("id") 
    State.Vals[id] = req.FormValue("val") 
    rw.Write([]byte("go to http://localhost:8080/?id=42")) 
} 

var form = `<html> 
    <body> 
     <form action="/" method="POST"> 
      ID: <input name="id" value="42" /><br /> 
      Val: <input name="val" /><br /> 
      <input type="submit" value="submit"/> 
     </form> 
    </body> 
</html>` 

func formHandler(rw http.ResponseWriter, req *http.Request) { 
    rw.Write([]byte(form)) 
} 

// for real routing take a look at gorilla/mux package 
func handler(rw http.ResponseWriter, req *http.Request) { 
    switch req.Method { 
    case "POST": 
     post(rw, req) 
    case "GET": 
     if req.URL.String() == "/form" { 
      formHandler(rw, req) 
      return 
     } 
     get(rw, req) 
    } 
} 

func main() { 
    fmt.Println("go to http://localhost:8080/form") 
    // thats the default webserver of the net/http package, but you may 
    // create custom servers as well 
    err := http.ListenAndServe("localhost:8080", http.HandlerFunc(handler)) 
    if err != nil { 
     fmt.Println(err) 
    } 
} 
+0

req.PostForm 정의되지 않은 (형식 * http.Request 필드 또는 메서드를 PostForm 없음) 받고 있어요 – kwolfe

+0

그것은 나를 위해 일한 이상 (go1.1) ... 그러나 나는 소스를 업데이트했는데, 지금 작동해야하고 조금 더 짧습니다 ... – metakeule

+1

@kwolfe 나는 그것을 보았습니다 - 그들은 * http.Request.Form (go1.0)에서 * http.Request로 필드를 변경했습니다. .FormValue (go1.1). 그러나 다시 작성된 변형 * http.Request.FormValue()는 두 버전 모두에서 작동합니다. 나는 온라인 문서가 그 버전을 반영하기 때문에 당신이 1.1.1로 갈 것을 강력히 제안 할 것이고 훨씬 더 빠르다. – metakeule