2015-02-09 41 views
5

Tôi nghĩ rằng câu hỏi này đã được hỏi trước (và có lẽ nhiều hơn một lần) nhưng tôi không thể tìm thấy nó ...Golang handlefunc với kênh

Im học Go, và tôi muốn mở rộng cổ điển ví dụ máy chủ web bằng cách gửi một kênh đến "người xử lý".

Tôi có điều tiêu chuẩn này:

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

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

Và bây giờ tôi muốn các "hello" chức năng để có thể viết những thứ trên một kênh, một ai đó để tiêu thụ ... Con đường tôi đã thực hiện với Các chức năng "bình thường" là tạo kênh:

c := make(chan string) 

và chuyển c trong khi gọi hàm. Một cái gì đó như:

dosomething(c) 

Nhưng ... tôi sẽ làm thế nào nếu tôi muốn "xin chào" để có quyền truy cập vào kênh c?

Trả lời

11

Có hai cách khác để thực hiện việc này (ngoài việc xuất kênh của bạn như trong câu trả lời trước).

Đầu tiên là sử dụng hàm để trả về hàm xử lý khác. Khi chức năng được trả về, nó sẽ tạo ra một đóng cửa xung quanh kênh.

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!") 
    } 
} 

Thứ hai là sử dụng một cấu trúc mà giữ kênh làm thành viên và sử dụng phương pháp con trỏ nhận để xử lý yêu cầu ...

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") 
} 

Đây là một ví dụ làm việc đầy đủ (chỉ cần nhấn/1 và/2 để xem hai ví dụ)

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

Cảm ơn bạn rất nhiều vì ví dụ tuyệt vời. Tôi đã kết thúc bằng cách sử dụng phương pháp 1, và nó thực hiện công việc một cách hoàn hảo. – plithner

+1

Đến từ python tôi không thể tìm ra cách để làm một điều đơn giản như vậy. Hài hước như thế nào có thực sự là một giải pháp rất đơn giản cho vấn đề, tất cả những gì cần thiết là một sự thay đổi mô hình. – Esser420

2

Có một số cách để giải quyết vấn đề này, cách đơn giản nhất là xác định kênh đã xuất trong gói và nhập gói đã biết ở nơi bạn muốn sử dụng kênh.

package mychannel 

var Chan = make(chan string) 
+0

Cảm ơn rất nhiều sự trợ giúp! Cuối cùng tôi đã sử dụng phương pháp do sberry đề xuất thay vào đó, nhưng tôi vẫn đánh giá cao sự trợ giúp! – plithner

+0

Điều này giống như "Mẫu Singleton kiểu Go". –

+0

@ SiuChingPong-AsukaKenji- nah, chỉ là một biến toàn cục. Bạn có thể có một singleton trong Go với một kiểu riêng với hàm hàm xây dựng công khai trả về biến riêng tư là cá thể của kiểu riêng, điều này sẽ thực thi mẫu đơn. Tôi không chắc rằng tôi đã nhìn thấy bất cứ ai mã trong Go làm nhiều điều đó mặc dù. – jmaloney

Các vấn đề liên quan