英文:
Golang handlefunc with channel
问题
我认为这个问题以前已经被问过了(可能不止一次),但我找不到了...
我正在学习Go语言,并且想通过向“处理程序”发送一个通道来扩展经典的Web服务器示例。
我有这个标准的代码:
func hello(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello world!")
}
func main() {
http.HandleFunc("/", hello)
http.ListenAndServe(":8000", nil)
}
现在我想让“hello”函数能够在通道上写入内容,以供其他人消费... 我在“普通”函数中的做法是创建一个通道:
c := make(chan string)
并将c传递给函数调用。类似这样:
dosomething(c)
但是...如果我想让“hello”函数能够访问通道c,我该怎么做呢?
英文:
I think this question has been asked before (and probably more than once) but I can't find it...
Im learning Go, and I wanted to extend the classical web server example by sending a channel to the "handler".
I have this standard thing:
func hello(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello world!")
}
func main() {
http.HandleFunc("/", hello)
http.ListenAndServe(":8000", nil)
}
And now I would like the "hello" function to be able to write stuff on a channel, for someone to consume... The way I have done with "normal" functions is to create a channel:
c := make(chan string)
and pass c in the call to the function. Something like:
dosomething(c)
But... how would I go about doing that if I want "hello" to get access to the channel c?
答案1
得分: 23
有两种其他方法可以实现这个(除了在上一个答案中导出通道的方法)。
第一种方法是使用一个函数返回另一个处理函数。当函数被返回时,它将在通道周围创建一个闭包。
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() {
// 方法1
logs := make(chan string)
go logLogs(logs)
handleHello := makeHello(logs)
// 方法2
passer := &DataPasser{logs: make(chan string)}
go passer.log()
http.HandleFunc("/1", handleHello)
http.HandleFunc("/2", passer.handleHello)
http.ListenAndServe(":9999", nil)
}
// 方法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)
}
}
// 方法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)
}
}
英文:
There are two other ways to do this (other than exporting your channels as in the previous answer).
The first is to use a function to return another handler function. When the function is returned, it will create a closure around the channel.
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!")
}
}
The second is to use a struct which holds the channel as a member and use pointer receiver methods to handle the request...
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")
}
This is a full working example (just hit /1 and /2 to see the two examples)
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)
}
}
答案2
得分: 2
有几种方法可以解决这个问题,最简单的方法是在一个包中定义一个导出的通道,并在需要使用该通道的地方导入该包。
package mychannel
var Chan = make(chan string)
英文:
There a few ways to solve this problem, the simplest is to define an exported channel in a package and import said package where ever you want to use the channel.
package mychannel
var Chan = make(chan string)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论