2015-02-09 54 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