ตกลงไหมที่จะเปิดช่องไว้หรือไม่?


160

ตกลงหรือไม่ที่จะปล่อยให้ช่อง Go เปิดตลอดไป (ไม่เคยปิดช่องสัญญาณ) ถ้าฉันไม่เคยตรวจสอบสถานะของมัน? มันจะนำไปสู่การรั่วไหลของหน่วยความจำ? รหัสต่อไปนี้ตกลงหรือไม่

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

คำตอบ:


236

มันโอเคที่จะเปิดช่อง Go ไว้ตลอดไปและอย่าปิด เมื่อไม่มีการใช้ช่องอีกต่อไปจะมีการรวบรวมขยะ

โปรดทราบว่ามีความจำเป็นต้องปิดช่องสัญญาณหากผู้รับกำลังมองหาการปิด การปิดช่องสัญญาณเป็นสัญญาณควบคุมในช่องที่ระบุว่าไม่มีข้อมูลเพิ่มเติม

คำถามการออกแบบ: การปิดช่อง


3
ฉันไม่แน่ใจว่าฉันเห็นด้วยกับการตอบสนองของลิงค์ ฉันมีหน่วยความจำรั่วในช่วง 2GB ทันทีที่ฉันเพิ่มปิดน้ำพุร้อนกลายเป็นหยด
Richard

9
@ Richard: อ่านกระทู้ทั้งหมดอย่างระมัดระวัง ผู้เขียนไปgcและผู้gccgoพูดช่องcloses closeไม่จำเป็นถ้าคุณกำลังมองหา นั่นเป็นคำแนะนำที่เชื่อถือได้
peterSO

6
@ peterSO อาจเป็นได้ แต่ฉันรู้ว่าสิ่งที่ฉันเห็นและนั่นคือสิ่งที่ฉันรายงานดังนั้นโปรดอย่าไล่ฉัน
Richard

1
ถ้าคุณมีช่องบัฟเฟอร์การเพิ่มข้อความควรใช้หน่วยความจำ อย่างไรก็ตามหากช่องของคุณไม่ถูกบัฟเฟอร์หรือไม่มีการเพิ่มการใช้งานหน่วยความจำจะไม่เพิ่มขึ้น
metakeule

อะไรประมาณนี้แล้ว: groups.google.com/forum/#!topic/golang-nuts/bfuwmhbZHYw ?
Kamil Dziedzic

31

ใช่มันก็โอเคที่จะเปิดช่อง ตามหนังสือภาษาการเขียนโปรแกรมไประบุ:

คุณไม่จำเป็นต้องปิดทุกช่องเมื่อทำเสร็จแล้ว จำเป็นต้องปิดช่องเมื่อจำเป็นที่จะต้องบอกให้ผู้รับทราบว่ามีการส่งข้อมูลทั้งหมดแล้ว ช่องที่ตัวรวบรวมขยะกำหนดว่าไม่สามารถเข้าถึงได้จะมีการเรียกคืนทรัพยากรไม่ว่าจะปิดหรือไม่ก็ตาม (อย่าสับสนกับการปิดไฟล์แบบเปิดมันเป็นสิ่งสำคัญที่จะต้องเรียก วิธีการปิดในทุก ๆ ไฟล์เมื่อคุณทำเสร็จแล้ว)


7

ใช่มันก็โอเคที่จะเปิดช่องและที่จริงมันเป็นเรื่องปกติ ช่องสัญญาณที่เปิดอยู่ไม่ได้เป็นการอ้างอิงถึงวัตถุช่องสัญญาณและดังนั้นจึงไม่ได้ป้องกันช่องเก็บขยะ


1

" หลักการทั่วไปข้อหนึ่งของการใช้แชนเนล Go คือไม่ปิดช่องจากฝั่งผู้รับและอย่าปิดช่องถ้าช่องมีผู้ส่งหลายคนพร้อมกัน "

ดังที่ได้กล่าวไว้อย่างชัดเจนในคำตอบข้างต้นว่าทุกช่องทางที่จะได้รับการ GCed ในที่สุดเมื่อมีการทำเครื่องหมายสำหรับการทำความสะอาดจึงเป็นโอเคที่จะออกจากช่องทางยกเลิกการปิดความแตกต่างเพียง แต่จะทำคือว่าช่องที่จะสามารถใช้ได้สำหรับgcหลังจากที่รอบไม่กี่บางทีถ้า ไม่ปิดอย่างชัดเจน

บทความต่อไปนี้และสิ่งนี้แสดงให้เห็นถึงวิธีต่างๆในการปิดช่องทางในกรณีที่ 1: N, N: 1 หรือ M: N (ผู้ส่ง: ผู้รับ)


-5

Go คือการรวบรวมขยะดังนั้นคุณไม่จำเป็นต้อง 'ฟรี' อะไรเลย

มีความเป็นไปได้ที่จะปิดช่องทาง แต่ส่วนใหญ่จะใช้เป็น - ปิด (ช่อง) - บอก goroutine (หรือโปรแกรมหลัก) ว่าไม่มีอะไรจะถูกส่งไปยังช่องสัญญาณนั้น


8
AFAIK แม้ในภาษาที่รวบรวมขยะโปรแกรมเมอร์ยังคงรับผิดชอบในการปลดปล่อยทรัพยากรที่ไม่มีการจัดการเช่นการปิดไฟล์ซ็อกเก็ตและอื่น ๆ ฉันต้องปิดช่องเหมือนไฟล์หรือไม่?
Kluyg

3
@Kluyg คำตอบคือไม่ คุณกำลังพูดถึงทรัพยากรระบบปฏิบัติการ (ช่องใดไม่) มันขึ้นอยู่กับทรัพยากรและภาษา แต่โดยทั่วไปจะแนะนำให้ปิดทรัพยากร OS ด้วยตนเองไม่ใช่เพราะ GC จะไม่ทำเช่นนั้น แต่เพราะมันเป็น nondeterministic ข้อผิดพลาดทั่วไปที่เกี่ยวข้องกับgotchaคือไฟล์ที่เปิดมากเกินไป คุณเปิดไฟล์ต่อไป ... คุณคาดหวังว่า GC จะทำเช่นนั้น ... คุณไม่มีหน่วยความจำไม่เพียงพอ (ดังนั้น GC จึงไม่เริ่มทำงาน) ... คุณไม่มีไฟล์ descriptors ในระดับระบบปฏิบัติการ ระบบปฏิบัติการฆ่ากระบวนการ :)
Pijusn

ฉันสับสนเกี่ยวกับสาเหตุนี้ได้ downvotes จำนวนมากดังนั้นในขณะที่มันถูกต้องตลอดเวลาและรัฐเช่นเดียวกับคำตอบที่ได้รับการยอมรับอื่น ๆ ...
Eja
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.