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?
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)
}
}
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With