Golang使用channel的handlefunc函数

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

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 &lt;- r.Host
io.WriteString(w, &quot;Hello world!&quot;)
}
}

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 &lt;- r.URL.String()
io.WriteString(w, &quot;Hello world&quot;)
}

This is a full working example (just hit /1 and /2 to see the two examples)

package main
import (
&quot;fmt&quot;
&quot;io&quot;
&quot;net/http&quot;
)
func main() {
// METHOD 1
logs := make(chan string)
go logLogs(logs)
handleHello := makeHello(logs)
// METHOD 2
passer := &amp;DataPasser{logs: make(chan string)}
go passer.log()
http.HandleFunc(&quot;/1&quot;, handleHello)
http.HandleFunc(&quot;/2&quot;, passer.handleHello)
http.ListenAndServe(&quot;:9999&quot;, nil)
}
// METHOD 1
func makeHello(logger chan string) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
logger &lt;- r.Host
io.WriteString(w, &quot;Hello world!&quot;)
}
}
func logLogs(logger chan string) {
for item := range logger {
fmt.Println(&quot;1. Item&quot;, item)
}
}
// METHOD 2
type DataPasser struct {
logs chan string
}
func (p *DataPasser) handleHello(w http.ResponseWriter, r *http.Request) {
p.logs &lt;- r.URL.String()
io.WriteString(w, &quot;Hello world&quot;)
}
func (p *DataPasser) log() {
for item := range p.logs {
fmt.Println(&quot;2. Item&quot;, 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)

huangapple
  • 本文由 发表于 2015年2月10日 05:37:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/28419876.html
匿名

发表评论

匿名网友

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

确定