Golang handlefunc with channel

pli*_*ner 7 go

我认为这个问题之前已被问过(可能不止一次),但我找不到它......

我正在学习Go,我想通过向"处理程序"发送一个频道来扩展经典的Web服务器示例.

我有这个标准的东西:

func hello(w http.ResponseWriter, r *http.Request) {
   io.WriteString(w, "Hello world!")
}

func main() {
    http.HandleFunc("/", hello)
    http.ListenAndServe(":8000", nil)
}
Run Code Online (Sandbox Code Playgroud)

现在我希望"hello"函数能够在一个频道上写东西,供有人使用...我用"普通"函数完成的方法是创建一个频道:

c := make(chan string) 
Run Code Online (Sandbox Code Playgroud)

并在调用函数时传递c.就像是:

dosomething(c)
Run Code Online (Sandbox Code Playgroud)

但是......如果我想要"hello"访问频道c,我该如何去做呢?

sbe*_*rry 17

还有另外两种方法(除了在上一个答案中导出频道).

第一种是使用函数返回另一个处理函数.返回函数时,它将在通道周围创建一个闭包.

func makeHello(logger chan string) func(http.ResponseWriter, *http.Request) {
    return func(w http.ResponseWriter, r *http.Request) {
        logger <- r.Host
        io.WriteString(w, "Hello world!")
    }
}
Run Code Online (Sandbox Code Playgroud)

第二种是使用一个将通道保存为成员的结构,并使用指针接收器方法来处理请求......

type DataPasser struct {
    logs chan string
}

func (p *DataPasser) handleHello(w http.ResponseWriter, r *http.Request) {
    p.logs <- r.URL.String()
    io.WriteString(w, "Hello world")
}
Run Code Online (Sandbox Code Playgroud)

这是一个完整的工作示例(只需点击/ 1和/ 2即可查看两个示例)

package main

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

func main() {
    // METHOD 1
    logs := make(chan string)
    go logLogs(logs)
    handleHello := makeHello(logs)

    // METHOD 2
    passer := &DataPasser{logs: make(chan string)}
    go passer.log()

    http.HandleFunc("/1", handleHello)
    http.HandleFunc("/2", passer.handleHello)
    http.ListenAndServe(":9999", nil)
}

// METHOD 1

func makeHello(logger chan string) func(http.ResponseWriter, *http.Request) {
    return func(w http.ResponseWriter, r *http.Request) {
        logger <- r.Host
        io.WriteString(w, "Hello world!")
    }
}

func logLogs(logger chan string) {
    for item := range logger {
        fmt.Println("1. Item", item)
    }
}

// METHOD 2

type DataPasser struct {
    logs chan string
}

func (p *DataPasser) handleHello(w http.ResponseWriter, r *http.Request) {
    p.logs <- r.URL.String()
    io.WriteString(w, "Hello world")
}

func (p *DataPasser) log() {
    for item := range p.logs {
        fmt.Println("2. Item", item)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 来自 python 我不知道如何做这么简单的事情。有趣的是,实际上有一个非常简单的解决方案来解决这个问题,所需要的只是范式转变。 (3认同)