Golang:异步HTTP服务器中的共享通信

huangapple go评论92阅读模式
英文:

Golang: Shared communication in async http server

问题

绝对的初学者,除了写一个简单的http服务器之外,对golang一无所知。我正在研究Go作为编写异步进程的可能性。如果您可以提供一个快速示例,说明如何实现这一点:

当收到Http请求'a'时,根据该请求中的POST负载(带有某种唯一标识符的POST或URL)启动一个操作。由'a'启动的异步进程将使用原始唯一标识符(请求'b')回复给同一服务器,而请求'a'仍然保持打开状态。我希望根据请求'b'的响应将该响应传递回请求'a'。

英文:

Absolute beginner to golang other than writing a simple http server. I'm researching Go as a possibility for writing an async process. If you could please provide a quick sample of how this might be accomplished:

Http request 'a' comes in, an operation is started based on POST payload in this request (with some sort of unique identifier in post or url). The async process started by 'a' will respond back to same server with original unique identifier (request 'b') while request 'a' is still open. I'd like to communicate that response back to request 'a' based on request 'b' response.

答案1

得分: 7

尽管可以使用通道来实现这一点,但在这种情况下,我更喜欢使用受互斥锁保护的哈希(映射)。

为了给你一个想法并让你开始:

package main

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

type state struct {
    *sync.Mutex // 继承锁定方法
    Vals map[string]string // 将id映射到值
}

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

func get(rw http.ResponseWriter, req *http.Request) {
    State.Lock()
    defer State.Unlock() // 确保在离开函数后解锁
    id := req.URL.Query().Get("id") // 如果你需要其他类型,请查看strconv包
    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))
}

// 对于真正的路由,请查看gorilla/mux包
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")
    // 这是net/http包的默认web服务器,但你也可以创建自定义服务器
    err := http.ListenAndServe("localhost:8080", http.HandlerFunc(handler))
    if err != nil {
        fmt.Println(err)
    }
}
英文:

Although it is possible to do this with channels,
I would prefer a hash (map) that is protected by a mutex,
since it is easier in this case.

To give you an idea and get you going:

package main

import (
    &quot;fmt&quot;
    &quot;net/http&quot;
    &quot;sync&quot;
)

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

var State = &amp;state{&amp;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(&quot;id&quot;) // if you need other types, take a look at strconv package
    val := State.Vals[id]
    delete(State.Vals, id)
    rw.Write([]byte(&quot;got: &quot; + val))
}

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

var form = `&lt;html&gt;
    &lt;body&gt;
        &lt;form action=&quot;/&quot; method=&quot;POST&quot;&gt;
            ID: &lt;input name=&quot;id&quot; value=&quot;42&quot; /&gt;&lt;br /&gt;
            Val: &lt;input name=&quot;val&quot; /&gt;&lt;br /&gt;
            &lt;input type=&quot;submit&quot; value=&quot;submit&quot;/&gt;
        &lt;/form&gt;
    &lt;/body&gt;
&lt;/html&gt;`

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 &quot;POST&quot;:
        post(rw, req)
    case &quot;GET&quot;:
        if req.URL.String() == &quot;/form&quot; {
            formHandler(rw, req)
            return
        }
        get(rw, req)
    }
}

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

huangapple
  • 本文由 发表于 2013年7月27日 04:51:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/17890830.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定