2015-02-09 126 views
5

我认为这个问题以前有人问(也许不止一次),但我无法找到它......Golang handlefunc与渠道

林学围棋,我想延长传统Web服务器实例通过发送频道到“处理程序”。

我有这个标准的东西:

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

func main() { 
    http.HandleFunc("/", hello) 
    http.ListenAndServe(":8000", nil) 
} 

现在我想的“你好”功能,能写东西的通道上,有人来消费......我有做的方法“正常”功能是创建一个通道:

c := make(chan string) 

并在调用函数时传递c。例如:

dosomething(c) 

但是......如果我想要“你好”来访问通道c,我该怎么做?

回答

11

还有两种方法可以做到这一点(除了导出您的频道,如在前面的答案)。

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

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) 
    } 
} 
+0

非常感谢你为这个伟大的例子。我最终使用了方法1,它完美地完成了这项工作。 – plithner 2015-02-10 09:50:13

+1

来自python我无法弄清楚如何做这样一个简单的事情。有趣的是,这个问题实际上是一个非常简单的解决方案,所需要的只是一个范式转变。 – Esser420 2018-01-03 12:27:08

2

有几种方法可以解决这个问题,最简单的方法是在软件包中定义一个导出的通道,然后导入你想要使用该通道的软件包。

package mychannel 

var Chan = make(chan string) 
+0

非常感谢您的帮助!最后,我使用了sberry提出的方法,但我仍然很感谢帮助! – plithner 2015-02-10 09:51:19

+0

这就像“Go风格的Singleton模式”。 – 2016-08-07 22:46:13

+0

@ SiuChingPong-AsukaKenji-nah,只是一个全局变量。你可以在Go中使用一个具有公共构造函数的私有类型的单例,该私有类型返回作为私有类型实例的私有变量,这将强制单例模式。我不确定我看到任何在Go中编码的人都能做到这一点。 – jmaloney 2016-08-08 16:28:25