Có thể để một kênh mở?


160

Tôi có thể để kênh Go mở mãi mãi (không bao giờ đóng kênh) nếu tôi không bao giờ kiểm tra trạng thái của kênh đó? Nó sẽ dẫn đến rò rỉ bộ nhớ? Mã sau có ổn không?

func (requestCh chan<- Request) GetResponse(data RequestData) Response {
    reply := make(chan Response)
    requestCh <- Request{data: data, replyCh: reply}
    return <-reply
}

Câu trả lời:


236

Bạn có thể để kênh Go mở mãi mãi và không bao giờ đóng kênh. Khi kênh không còn được sử dụng, nó sẽ được thu gom rác.

Lưu ý rằng chỉ cần đóng một kênh nếu người nhận đang tìm cách đóng. Đóng kênh là tín hiệu điều khiển trên kênh cho biết không có thêm dữ liệu nào theo sau.

Câu hỏi thiết kế: Đóng kênh


3
Tôi không chắc chắn tôi đồng ý với phản hồi của liên kết. Tôi bị rò rỉ bộ nhớ trong phạm vi 2GB. Ngay khi tôi thêm vào, mạch nước phun trở nên nhỏ giọt.
Richard

9
@Richard: Đọc kỹ toàn bộ chủ đề. Tác giả của Go gcvà tác giả của gccgokênh nói closekhông cần thiết, trừ khi bạn đang tìm kiếm a close. Đó là lời khuyên có thẩm quyền.
peterSO

6
@peterSO, điều đó có thể nhưng tôi biết những gì tôi đã thấy và đó là những gì tôi đã báo cáo vì vậy xin đừng loại bỏ tôi.
Richard

1
Chà, nếu bạn có một kênh đệm, việc thêm tin nhắn vào kênh sẽ sử dụng bộ nhớ. Tuy nhiên, nếu kênh của bạn không được đệm hoặc không có gì được thêm vào, bộ nhớ sẽ không tăng.
metakeule


31

Có, nó là ok để giữ một kênh mở. Như cuốn sách ngôn ngữ lập trình đi đã nêu:

Bạn không cần phải đóng mọi kênh khi bạn hoàn thành nó. Chỉ cần đóng một kênh khi điều quan trọng là phải nói với các con khỉ đột nhận rằng tất cả dữ liệu đã được gửi. Một kênh mà người thu gom rác xác định là không thể truy cập được sẽ lấy lại tài nguyên của nó cho dù nó có bị đóng hay không. (Đừng nhầm lẫn điều này với thao tác đóng cho các tệp đang mở. Điều quan trọng là gọi phương thức Đóng trên mỗi tệp khi bạn hoàn thành với nó.)


7

Có, bạn có thể để kênh mở và thực tế nó là điển hình. Một kênh đang mở không tạo thành một tham chiếu đến đối tượng kênh và do đó không giữ cho nó không bị thu gom rác.


1

" Một nguyên tắc chung của việc sử dụng các kênh Go là không đóng kênh từ phía người nhận và không đóng kênh nếu kênh có nhiều người gửi đồng thời. "

Như đã đề cập rõ ràng trong câu trả lời ở trên rằng mọi kênh sẽ được xử lý cuối cùng một khi nó được đánh dấu để dọn dẹp, vì vậy không sao để kênh không bị đóng, điểm khác biệt duy nhất là kênh đó sẽ khả dụng gc sau một vài chu kỳ có thể nếu không đóng cửa rõ ràng.

Ngoài ra các bài viết sau nàynày show nhiều cách khác nhau để đóng một kênh trong trường hợp 1: N, N: 1 hoặc M: N (người gửi: thu)


-5

Đi là rác được thu thập, vì vậy bạn không thực sự phải 'miễn phí' bất cứ điều gì.

Có khả năng đóng các kênh, nhưng nó chủ yếu được sử dụng như - đóng (kênh) - nói với goroutine (hoặc chương trình chính) rằng sẽ không có gì khác được gửi trên kênh đó.


8
AFAIK ngay cả trong một ngôn ngữ được thu thập rác, một lập trình viên vẫn chịu trách nhiệm giải phóng các tài nguyên không được quản lý, ví dụ như đóng các tệp, ổ cắm, v.v. Tôi có cần phải đóng kênh như một tập tin không?
Kluyg

3
@Kluyg Câu trả lời là không. Bạn đang nói về tài nguyên hệ điều hành (kênh nào không có). Nó phụ thuộc vào tài nguyên và ngôn ngữ nhưng thông thường nên đóng tài nguyên hệ điều hành theo cách thủ công không phải vì GC sẽ không làm như vậy mà vì nó không đặc biệt. Gotcha liên quan phổ biến nhất là quá nhiều lỗi mở tệp . Bạn tiếp tục mở tệp ... Bạn hy vọng GC sẽ làm như vậy ... Bạn không hết bộ nhớ (do đó, GC không khởi động) ... Bạn hết bộ mô tả tệp ở cấp HĐH. Hệ điều hành giết chết quá trình :)
Pijusn

Tôi bối rối về lý do tại sao điều này lại có quá nhiều lượt tải xuống trong khi nó đúng toàn bộ thời gian và nói giống như các câu trả lời được chấp nhận khác ...
eja
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.