带通道的 Golang handlefunc
Golang handlefunc with channel
我想这个问题以前有人问过(而且可能不止一次)但是我找不到...
我正在学习 Go,我想通过向 "handler" 发送一个频道来扩展经典的 Web 服务器示例。
我有这个标准的东西:
func hello(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello world!")
}
func main() {
http.HandleFunc("/", hello)
http.ListenAndServe(":8000", nil)
}
现在我希望 "hello" 函数能够在频道上写东西,供某人消费...我使用 "normal" 函数的方法是创建一个频道:
c := make(chan string)
并在函数调用中传递 c。类似于:
dosomething(c)
但是...如果我想 "hello" 访问频道 c,我该怎么做呢?
有几种方法可以解决这个问题,最简单的方法是在包中定义一个导出通道,然后在您想要使用该通道的任何地方导入该包。
package mychannel
var Chan = make(chan string)
还有其他两种方法可以做到这一点(除了像上一个答案那样导出频道)。
第一种是使用一个函数来return另一个处理函数。当函数被 returned 时,它将在通道周围创建一个闭包。
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!")
}
}
第二种是使用将通道作为成员保存的结构,并使用指针接收器方法来处理请求...
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")
}
这是一个完整的工作示例(只需点击 /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)
}
}
我想这个问题以前有人问过(而且可能不止一次)但是我找不到...
我正在学习 Go,我想通过向 "handler" 发送一个频道来扩展经典的 Web 服务器示例。
我有这个标准的东西:
func hello(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello world!")
}
func main() {
http.HandleFunc("/", hello)
http.ListenAndServe(":8000", nil)
}
现在我希望 "hello" 函数能够在频道上写东西,供某人消费...我使用 "normal" 函数的方法是创建一个频道:
c := make(chan string)
并在函数调用中传递 c。类似于:
dosomething(c)
但是...如果我想 "hello" 访问频道 c,我该怎么做呢?
有几种方法可以解决这个问题,最简单的方法是在包中定义一个导出通道,然后在您想要使用该通道的任何地方导入该包。
package mychannel
var Chan = make(chan string)
还有其他两种方法可以做到这一点(除了像上一个答案那样导出频道)。
第一种是使用一个函数来return另一个处理函数。当函数被 returned 时,它将在通道周围创建一个闭包。
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!")
}
}
第二种是使用将通道作为成员保存的结构,并使用指针接收器方法来处理请求...
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")
}
这是一个完整的工作示例(只需点击 /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)
}
}