ستاس أفاناسييف. جونو. خطوط الأنابيب على أساس io.Reader / io.Writer. الجزء 2

في التقرير ، سنتحدث عن مفهوم io.Reader / io.Writer ، ولماذا هم بحاجة إليها ، وكيفية تنفيذها بشكل صحيح وما هي المزالق الموجودة في هذا الصدد ، وكذلك حول بناء خطوط الأنابيب على أساس io.Reader / io.Writer القياسي والمخصص .



ستاس أفاناسييف. جونو. خطوط الأنابيب على أساس io.Reader / io.Writer. الجزء الأول

خطأ "على الثقة"


فارق بسيط آخر: في هذا التطبيق هناك "باجول". تم تأكيد هذا الخطأ من قبل المطورين (كتبت لهم عن ذلك). ربما شخص يعرف ما هو هذا "باجول"؟ إنه على الشريحة هو الخط قبل الأخير:



فهو مرتبط بثقة كبيرة في القارئ الملفوف: إذا أعاد القارئ عددًا سالبًا من وحدات البايت ، فإن الحد الذي نرغب في الحصول عليه بعدد وحدات البايت المطروحة يزيد. وفي بعض الحالات ، يعد هذا خطأً خطيرًا لا يمكنك فهمه على الفور.

لقد كتبت في المشكلة: لنفعل شيئًا ، فلنصلح ذلك! ثم كشفت طبقة من المشاكل ... أولاً ، أخبروني أنه إذا أضفت هذا الفحص الآن هنا ، فسيتعين عليك إضافة هذا الفحص في كل مكان ، وهناك عشرات من هذه الأماكن. إذا أردنا تحويل هذا إلى جانب العميل ، فنحن بحاجة إلى تحديد عدد من القواعد التي سيصادق العميل من خلالها على البيانات (وقد يكون هناك أيضًا خمسة أو اثنتين منها). اتضح أن كل هذا يحتاج إلى نسخ.

أوافق على أن هذا ليس هو الأمثل. ثم دعونا نأتي إلى إصدار ثابت! لماذا لدينا تطبيق واحد للمكتبة القياسية التي لا تثق بأي شيء ، بينما يثق الآخرون بكل شيء على الإطلاق؟

بشكل عام ، بينما كنت أكتب رأيي المدني ، أفكر في الأمر ، أغلقنا المسألة بالتعليقات - "لن نفعل أي شيء. وداعا"! جعلوني أبدو مثل نوع من الحمقى ... بأدب ، بالطبع ، لا يمكنك العثور على خطأ.

بشكل عام ، لدينا الآن مشكلة. وهو يتألف من حقيقة أنه ليس من الواضح من الذي ينبغي عليه التحقق من صحة بيانات القارئ الملفوف. إما العميل ، أو نثق تمامًا في العقد ... لدينا حل واحد! إذا كان هناك وقت متبقي ، فسأخبرنا بذلك.

دعنا ننتقل إلى الحالة التالية.

Teereader


نظرنا إلى مثال لكيفية التفاف بيانات Reader. المثال التالي للأنابيب هو تجاوز بيانات القارئ في الكاتب. هناك حالتان.

الوضع الأول. نحن بحاجة إلى قراءة البيانات من Reader ، ونسخها بطريقة ما إلى Writer (بشفافية) والعمل معها كما هو الحال مع Reader. يوجد تنفيذ TeeReader لهذا الغرض. يتم تقديمه في مقتطف التنفيذ العلوي:



يعمل مثل فريق Tee على Unix. أعتقد أن الكثير منكم سمع عن هذا.
لاحظ أن هذا التطبيق يتحقق من عدد وحدات البايت التي يقرأها من القارئ الملتف. انظر الشروط في السطر الثاني؟ لأنه عندما تكتب مثل هذا التنفيذ ، يكون بديهيًا: في حالة وجود رقم سالب ، ستصاب بالذعر. وهذا مكان آخر نثق فيه بالقارئ الملفوف! أذكرك أن هذه كلها مكتبات قياسية.

دعنا ننتقل إلى حالة ، على سبيل المثال ، كيفية استخدامها. ماذا سنفعل في المقتطف السفلي؟ سنقوم بتنزيل ملف robot.txt من golang.org باستخدام عميل http القياسي.

كما تعلمون ، يقوم عميل http بإرجاع بنية استجابة لنا ، حيث يكون حقل Body عبارة عن تنفيذ لواجهة Reader. يجب توضيح ذلك بقول أن هذا هو تنفيذ واجهة ReadCloser. لكن ReadCloser هي مجرد واجهة مبنية من Reader و Closer. هذا هو القارئ ، والذي يمكن إغلاقه بشكل عام.

في هذا المثال (في المقتطف السفلي) نجمع TeeReader ، والذي سيقرأ البيانات من هذا النص ويكتبه في ملف. للأسف ، ظل إنشاء الملف اليوم خلف الكواليس ، لأن كل شيء لم يكن مناسبًا. ولكن ، مرة أخرى ، إذا نظرت إلى dendrogram ، فإن نوع الملف يطبق واجهة Writer ، أي يمكننا الكتابة إليه. إنه واضح.

قمنا بتجميع TeeReader وقراءتها باستخدام ReadAll. كل شيء يعمل كما هو متوقع: نطرح النص الناتج ونكتبه في ملف ونراه في الأسد.

طريقة المبتدئين


الحالة الثانية. نحتاج فقط إلى قراءة البيانات من Reader وكتابتها إلى Writer. الحل واضح ...

عندما بدأت العمل مع Go ، قمت بحل مثل هذه المشاكل كما في الشريحة:



لقد قمت بتحديد موقع المخزن المؤقت ، وملأته ببيانات من Reader ، ونقل الشريحة المعبأة إلى Writer. كل شيء بسيط.

نقطتان. أولاً ، ليس هناك ما يضمن أنه سيتم طرح القارئ بالكامل في مكالمة واحدة إلى طريقة القراءة ، لأنه قد تكون هناك بيانات متبقية (بطريقة جيدة ، يجب أن يتم ذلك في حلقة).

النقطة الثانية هي أن هذا المسار ليس الأمثل. إليك رمزًا مميزًا مكتوبًا أمامنا.

لهذا ، هناك مجموعة خاصة من المساعدين في المكتبة القياسية - وهم Copy و CopyN و CopyBuffer.

نسخه. الكاتب و ReaderFrom


يقوم io.Copy بشكل أساسي بما كان عليه في الشريحة السابقة: يقوم بتخصيص مخزن مؤقت افتراضي 32 كيلوبايت ويكتب البيانات من Reader إلى Writer (يظهر توقيع هذه النسخة على المقتطف العلوي):



بالإضافة إلى روتين القالب هذا ، فإنه يحتوي أيضًا على سلسلة من التحسينات الصعبة. وقبل أن نتحدث عن هذه التحسينات ، نحتاج إلى التعرف على واجهتين إضافيتين:

  • الكاتب إلى ؛
  • قراءة من.

الوضع الافتراضي. يعمل القارئ الخاص بك مع المخزن المؤقت للذاكرة. لقد قام بالفعل بنقله ، ويكتب ، ويقرأ شيئًا من هناك ، أي أنه قد تم بالفعل نقل مكان تحته. تريد قراءة هذا القارئ في مكان ما من الخارج.

لقد رأينا بالفعل كيف يحدث هذا: يتم إنشاء المخزن المؤقت ، يتم تمرير المخزن المؤقت ، الذي يتم تمريره إلى طريقة القراءة ؛ القارئ ، الذي يعمل مع الذاكرة ، يخرجه من القطعة المكررة ... ولكن هذا لم يعد الأمثل - تم تغيير المكان. لماذا تفعل ذلك مرة أخرى؟



في مكان ما قبل 5-6 سنوات (هناك رابط لقائمة التغيير) تم إنشاء واجهتين: WriteTo و ReadFrom ، والتي يتم تنفيذها محليًا. يقوم القارئ بتطبيق WriteTo ، وينفذ الكاتب القراءة من. اتضح أن Reader ، بعد وجود شريحة مع البيانات المنسوخة بالفعل ، يمكنه تجنب موقع إضافي وقبول أساليب الكتابة إلى الكاتب وتمرير المخزن المؤقت المتاح في الداخل.

هذه هي الطريقة التي يعمل بها تطبيق bytes.Buffer و bufio. وإذا نظرت إلى مخطط الشقوق مرة أخرى ، سترى أن هاتين الواجهتين ليستا شائعتين. يتم تنفيذها فقط لتلك الأنواع التي تعمل مع المخزن المؤقت الداخلي - حيث تم نقل الذاكرة بالفعل. لن يساعدك ذلك على تجنب البلاغة في كل مرة ، ولكن فقط إذا كنت تعمل بالفعل مع قطعة تم نقلها.

يعمل ReaderFrom بطريقة مماثلة (يتم تنفيذه فقط بواسطة الكاتب). يقرأ ReaderFrom كامل القارئ ، والذي يأتي كحجة إليه (قبل EOF) ويكتب في مكان ما في التنفيذ الداخلي للكاتب.

تنفيذ CopyBuffer


يوضح هذا المقتطف تنفيذ مساعد copyBuffer. تُستخدم نسخة CopyBuffer غير القابلة للتصدير هذه تحت غطاء io.Copy و CopyN و CopyBuffer.

وهنا هناك فارق بسيط صغير جدير بالذكر. تم تحسين CopyN مؤخرًا - غير مرتبط بهذا المنطق. هذا هو التحسين الذي تحدثت عنه سابقًا: قبل إنشاء مخزن مؤقت إضافي بسعة 32 كيلوبايت ، يتم إجراء فحص - ربما يقوم مصدر البيانات بتنفيذ واجهة WriterTo ، وليس هناك حاجة إلى هذا المخزن المؤقت الإضافي؟

إذا لم يحدث ذلك ، نتحقق من ذلك: ربما يقوم الكاتب بتنفيذ ReaderFrom لربطها بدون هذا الوسيط؟ إذا لم يحدث هذا ، يبقى الأمل الأخير: ربما تم إعطاؤنا نوعًا من المخزن المؤقت الذي تم نقله يمكننا استخدامه؟



هكذا يعمل io.Copy.

هناك مشكلة واحدة ، وهي شبه مقترح ، وشبه علة - ليس من الواضح ماذا. كانت معلقة لمدة عام ونصف. يبدو أن هذا: CopyBuffer غير صحيح دلالة.

لسوء الحظ ، لا يوجد توقيع لهذه النسخة ، ولكن يبدو تمامًا مثل هذه الطريقة غير القابلة للتصدير.

عند استدعاء copyBuffer على أمل تجنب موقع إضافي ، قم بتمرير بعض شرائح الشريحة التي تم نقلها إلى هناك ، يعمل المنطق التالي: إذا كان Reader أو Writer يحتويان على واجهات WriterTo و ReaderFrom ، فلا يوجد ضمان بأنك ستكون قادرًا على تجنب هذا الموقع. تم قبول هذا كمقترح ووعد بالتفكير فيه في Go 2.0. في الوقت الحالي ، تحتاج فقط إلى معرفة.

العمل مع io.Pipe. PipeReader و pipeWriter


حالة أخرى: تحتاج إلى الحصول على بيانات من الكاتب بطريقة أو بأخرى في Reader. حالة حياة جميلة.

تخيل أن لديك بالفعل بعض البيانات ، وأنها تنفذ واجهة القارئ - كل شيء واضح مع هذا. أنت بحاجة إلى ضغط هذه البيانات و "تعديلها" وإرسالها إلى S3. ما هو فارق بسيط؟ ..
من عمل مع نوع gzip في حزمة الامتياز يعرف أن gzip'er نفسه مجرد وكيل: فهو يأخذ البيانات إلى نفسه ، وينفذ واجهة الكاتب ، ويكتب البيانات ، وسيفعل شيء ما بها ، و ثم يجب أن أسقطهم في مكان ما. على المنشئ ، يستغرق تنفيذ واجهة الكاتب.

وفقًا لذلك ، نحتاج هنا إلى نوع من الكاتب المتوسط ​​، حيث سنقوم بإسقاط البيانات المضغوطة بالفعل التي تم أرشفتها في المرحلة الأولى. خطوتنا التالية هي تحميل هذه البيانات إلى S3. ويقبل عميل AWS القياسي واجهة io.Reader كمصدر بيانات.



تُظهر الشريحة خط الأنابيب - تُظهر كيف تبدو: نحن بحاجة إلى تجاوز البيانات للتجاوز من Reader إلى Writer ، من Writer إلى Reader. كيف افعلها؟

تحتوي المكتبة القياسية على ميزة رائعة - io.Pipe. تقوم بإرجاع قيمتين: pipeReader و pipeWriter. هذا الزوج مرتبط بشكل لا ينفصم. تخيل "هاتفًا للأطفال" في أكواب بها حبال: لا معنى للتحدث في فنجان واحد بينما لا يستمع أحد إلى الطرف الآخر ...



ماذا يفعل هذا الأنبوب io.Pipe؟ لن يقرأ حتى يكتب أحد البيانات. والعكس بالعكس ، لن يكتب أي شيء حتى يقرأ أحد هذه البيانات في الطرف الآخر. هنا مثال على التنفيذ:



سنفعل الشيء نفسه هنا. سنقرأ ملف robot.txt ، الذي تمت قراءته من قبل ، وسنقوم بضغطه باستخدام gzip الخاص بنا وإرساله إلى S3.

  • في السطر الأول ، يتم إنشاء زوج - pipeReader ، pipeWriter. بعد ذلك ، يجب أن نقوم بتشغيل غوروتين واحد على الأقل ، والذي سيقرأ البيانات من طرف واحد (نوع من الأنبوب). في هذا gorutin ، قم بتشغيل برنامج التحميل بمصدر بيانات (المصدر - pipeReader).
  • في الخطوة التالية ، نحتاج إلى ضغط البيانات. نقوم بضغط البيانات وكتابتها على pipeWriter (ستكون الطرف الآخر من الأنبوب) ، ويستقبل تشغيل الغوروتين البيانات بالفعل في الطرف الآخر من الأنبوب ويقرأه. عندما تكون هذه الشطيرة كاملة جاهزة ، كل ما تبقى هو إشعال الفتيل ...
  • انظر: io.Copy على السطر الأخير يكتب البيانات من النص إلى gzip الذي أنشأناه (أي من Reader إلى Writer). كل هذا يعمل كما هو متوقع.

يمكن حل هذا المثال بطريقة أخرى. إذا كنت تستخدم أي تطبيق يطبق كلاً من Reader و Writer. ستكتب أولاً البيانات فيه ، ثم تقرأها.
لقد كان عرضًا واضحًا لكيفية العمل مع io.Pipe.

تطبيقات أخرى


هذا كل شيء بالنسبة لي. نأتي إلى تطبيقات مثيرة للاهتمام أود الحديث عنها.



لم أقل أي شيء عن MultiReader ولا عن MultiWriter. وهذا تطبيق رائع آخر للمكتبة القياسية ، والذي يسمح لك بربط التطبيقات المختلفة. على سبيل المثال ، يكتب برنامج MultiWriter لجميع الكتّاب في نفس الوقت ، ويقرأ برنامج MultiReader القراء بالتتابع.

يسمى تنفيذ آخر limio. يسمح لك بتعيين حد للطرح. يمكنك ضبط السرعة بالبايت في الثانية التي يحتاج قارئك لقراءتها.

تطبيق آخر مثير للاهتمام هو مجرد تصور لتقدم القراءة - شريط التقدم (من بعض المتأنق). يطلق عليه ioprogress.

لماذا قلت كل هذا؟ ماذا قصدت بذلك؟



  • إذا كنت تحتاج فجأة إلى تنفيذ واجهات القارئ والكاتب ، فقم بذلك بشكل صحيح. لا يوجد قرار واحد حتى الآن من المسؤول عن التنفيذ - سنفترض أن الجميع يثق في العقد. لذلك تحتاج إلى الالتزام به بشكل لا تشوبه شائبة.
  • إذا كانت حالتك تعمل مع مخزن مؤقت تم إعادة ضبط موقعه ، فلا تنس واجهات ReaderFrom و WriterTo.
  • إذا كنت في طريق مسدود وتحتاج إلى أمثلة - راجع المكتبة القياسية ، فهناك العديد من التطبيقات الرائعة التي يمكنك الاعتماد عليها. هناك وثائق هناك.
  • إذا كان هناك شيء غير مفهوم تمامًا لك ، فلا تتردد في كتابة المشكلات. الرجال هناك كافون ، يستجيبون بسرعة ، بأدب شديد ويساعدونك بكفاءة.



هذا كل شيء بالنسبة لي. شكرا لقدومك!

الأسئلة


سؤال من الجمهور (ب): - لدي سؤال بسيط ، على ما أعتقد. يرجى إخبارنا عن بعض حالات الاستخدام من الحياة: والتي تم استخدامها ولماذا؟ قلت أن القارئ / الكاتب يعيد الطول الذي قرأه. هل سبق لك أن واجهت أي مشاكل مع هذا ؛ متى طلبت القراءة (ليس فقط ReadAll موجودًا) ، ولكن لم ينجح شيء؟

SA: - يجب أن أعترف بصراحة أنه لم يكن لدي مثل هذه الحالات ، لأنني عملت دائمًا مع تطبيقات المكتبة القياسية. ولكن من الناحية الافتراضية ، مثل هذا الوضع ممكن. بالنسبة لحالات معينة ، غالبًا ما نجمع أنابيب متعددة الطبقات ، وإذا سمحت افتراضيًا بمثل هذا الخطأ ، فسوف ينهار الأنبوب بأكمله ...

س:- هذه ليست حشرة. دعنا نخبرك عن تجربتي الصغيرة. كانت لدي مشكلة مع Booking.com: لقد استخدموا برنامج التشغيل الذي كتبته ، وكان لديهم مشكلة - لم يكن هناك شيء يعمل. هناك بروتوكول ثنائي قياسي قمنا به ؛ محليًا ، كل شيء يعمل بشكل جيد ، الجميع بخير ، ولكن اتضح أن لديهم شبكة سيئة للغاية مع مركز بيانات. ثم لم يرد Reader كل شيء (بطاقات الشبكة السيئة ، شيء آخر).

كريس: - ولكن إذا لم يعيد كل شيء ، فلا يجب أن يعيد علامة النهاية (النهاية) ، ويجب أن يأتي العميل مرة أخرى. بموجب العقد الموصوف ، لا يجب على Reader ... دعنا نقول فقط أن Reader ، بالطبع ، يقرر متى يريد أن يأتي ، عندما لا يريد ، ومع ذلك ، إذا كان يريد قراءة كل شيء ، يجب عليه الانتظار حتى EOF.

في:"ولكن هذا هو بالضبط بسبب الاتصال". هذه هي بالضبط المشكلة التي حدثت في حزمة net القياسية.

ك أ: وهل عاد م.

س: - لم يرد كل شيء - ببساطة لم يقرأ كل شيء. قلت له: "اقرأ الـ 20 بايت التالية". هو يقرأ. وأنا لا أقرأ كل شيء.

SA: - هذا ممكن افتراضيًا ، لأنه مجرد واجهة تصف بروتوكول الاتصال. من الضروري مشاهدة القضية وتفكيكها على وجه التحديد. هنا يمكنني فقط أن أجيبك بأن العميل ، نظريًا ، كان يجب أن يأتي مرة أخرى إذا لم يتلق كل ما يريده. لقد طلبت منه شريحة 20 بايت ، وطرح 15 لك ، لكن EOF لم يأت - يجب أن تذهب مرة أخرى ...

س: - هناك io.ReadFull لهذا الموقف. وهي مصممة خصيصًا لقراءة الشريحة حتى النهاية.

المرجع المصدق:- نعم. لم أقل أي شيء عن ReadFull.

س: - هذه حالة طبيعية تمامًا عندما لا يملأ Read الشريحة بالكامل. يجب أن تكون مستعدًا لذلك.

SA: - هذه حالة متوقعة للغاية!

سؤال: - شكراً على التقرير - لقد كان شيقاً. أستخدم القراء في وكيل صغير وبسيط يقرأ http ويكتب بالعكس. أستخدم إغلاق القارئ لحل مشكلة واحدة - لإغلاق ما أقرأه في كل وقت. هل أحتاج إلى الثقة في العقد بشكل أعمى؟ قلت أنه قد تكون هناك مشاكل. أو إضافة شيكات إضافية؟ من الممكن نظريًا أن شيئًا ما لن يأتي بالكامل على هذا الموقع. هل أحتاج إلى القيام بهذه الفحوصات الإضافية ولا أثق بالعقد؟

المرجع المصدق:- أود أن أقول هذا: إذا كان تطبيقك يتسامح مع هذه الأخطاء (على سبيل المثال ، إذا كنت تثق تمامًا في العقد) ، فربما لا. ولكن إذا كنت لا ترغب في الحصول على "ذعر" في نفسك (كما أظهرته في القراءة السلبية في byte.Buffer) ، فما زلت أتحقق.
ولكن هذا "متروك لكم". ما الذي يمكنني أن أوصيك به؟ أعتقد أن مجرد وزن الإيجابيات والسلبيات. ماذا يحدث إذا حصلت فجأة على عدد سالب من البايت؟

سؤال: - شكرا على التقرير. لسوء الحظ ، لا أعرف أي شيء في Go. في حالة حدوث "حالة من الذعر" ، هل هناك أي طريقة لاعتراض هذه المعلومات والحصول على معلومات حول ماذا وأين وكيف يتم التحيز لتجنب المشاكل ليلة الجمعة؟

ك أ: - نعم. تتيح لك آلية الاسترداد "التقاط" حالة من الذعر وإخراجها دون السقوط ، نسبيًا.



في:- كيف تتسق توصياتك لاستخدام تطبيقات الكاتب والقارئ مع الأخطاء التي يتم إرجاعها عند تنفيذ مآخذ الويب. لن أعطي مثالاً ملموسًا ، ولكن هل يتم استخدام نهاية الملف دائمًا هناك؟ بقدر ما أتذكر ، تنتهي الرسالة ببعض المعاني الأخرى ...

SA: - هذا سؤال جيد ، لأنه ليس لدي شيء للإجابة عليه. يجب مشاهدتة! إذا لم يأت EOF ، فيجب على العميل ، إذا كان يريد الحصول على كل شيء ، أن يذهب مرة أخرى.

س: - متى كانت الأنابيب قادرة على التجميع؟ هل هناك اعتقادات داخلية بأن الأنابيب لا تستحق جمع أكثر من خمسة مشاركين ، أو مع فروع؟ كم من الوقت تمكنت من بناء شجرة من هذه الأنابيب (اقرأ ، اكتب)؟

المرجع المصدق:- في عملي ، تعد حوالي خمس مكالمات متتالية هي الأفضل ، لأنه من الصعب تصحيحها ، ضع في اعتبارك ما يتدفق وأين تذهب. يتم الحصول على هيكل متفرعة جميلة. ولكن أود أن أقول في مكان ما 5-7 كحد أقصى.

س: - 5-7 - في هذه الحالة؟

SA: - هذا يقرأ ، على سبيل المثال ، بعض البيانات. تحتاج إلى التعهد ، وما تقوم بتسجيل الدخول ، تحتاج إلى قطعه. تعهدت - ثم تقرأ هذه البيانات - تحتاج إلى إعادة إرسالها إلى بعض التخزين (حسنًا ، افتراضيًا). في أي مساحة تخزين تنفذها واجهة الكاتب. باستخدام هذا الأنبوب ، تحدث 5-6 خطوات ، على الرغم من أنه في إحدى الخطوات لا يزال يتفرع إلى الجانب ، وتستمر في العمل مع Reader.

في:- وفقًا لطريقة المبتدئين ، كان لديك شريحة مثيرة للاهتمام. هل يمكنك الإشارة إلى نقطتين أو ثلاث نقاط أخرى مثيرة للاهتمام ، ولكن الآن من الأفضل عدم القيام بها ، ولكن القيام بذلك بشكل مختلف الآن؟

SA: - مع هذه الشريحة ، أردت أن أبين بالضبط كيفية القيام بذلك دون الحاجة إلى قراءة Reader. لم يخطر ببالي أبداً أن شيئًا مثل طريقة المبتدئين ... ربما يكون هذا هو الخطأ الرئيسي ، وهو النمط الرئيسي الذي يجب تجنبه عند العمل مع القراء.
المذيع: - أود أن أضيف بمفردي أنه من المهم للغاية بالنسبة للمبتدئين قراءة جميع وثائق حزمة io ، على جميع الواجهات الموجودة ، وفهمها. لأنه في الواقع يوجد الكثير منها ، وغالبًا ما تبدأ في فعل شيء خاص بك ، على الرغم من أنه موجود بالفعل هناك ويتم تنفيذه بشكل صحيح ("صحيح" - مع مراعاة جميع الميزات).
سؤال القائد: - كيف نعيش أكثر؟

ك أ: - سؤال جيد! لقد وعدت أن أقول ما إذا كان لدينا الوقت. نتيجة لمناقشة الخلل ، توصل LimitedReader إلى القرار التالي: جعل الواقي من نوع الواقي بطريقة ما ، والذي يحمي من التهديدات الخارجية ، لف بعض القارئ الذي لا تثق به - لمنع أي إصابة من دخول النظام الخاص بك.

وفي هذا القارئ ، تقوم بتنفيذ جميع عمليات التحقق التي لا يمكنك إجراؤها: على سبيل المثال ، القراءة السلبية ، والتجارب مع عدد وحدات البايت (لنفترض أنك أرسلت شريحة من 10 بايت ، واستردت 15 - كيف تتفاعل مع هذا؟) ... في هذا القارئ ويمكنك تنفيذ مجموعة من عمليات التحقق هذه. قلت: "ربما دعنا نضيف إلى المكتبة القياسية ، لأنه سيكون من المفيد للجميع استخدامها"؟

لقد أعطيت إجابة مفادها أنه لا يوجد أي معنى في هذا - هذا شيء بسيط يمكنك تنفيذه بنفسك. الكل. نحن نعيش. نحن نثق في الرجال العقد. لكنني لن أثق.



س: - عندما نعمل مع القراء والكُتّاب ، هناك فرصة للتعرّف على "قنبلة" gzip ... كم نثق في ReadAll و WriteAll؟ أو ، مع ذلك ، تنفيذ قراءة المخزن المؤقت والعمل فقط مع المخزن المؤقت؟

المرجع المصدق:- يستخدم ReadAll نفسه وحدات البايت فقط. عندما تريد استخدام هذا الشيء أو ذاك ، فمن المستحسن أن تدخل وترى كيف يتم تنفيذ هذه "الشجاعة". مرة أخرى ، هذا يعتمد على متطلباتك: إذا كنت لا تتسامح مع مثل هذه الأخطاء التي أظهرتها ، فأنت بحاجة لمعرفة ما إذا تم التحقق من ما يأتي من القارئ الملفوف. إذا لم يتم تحديده ، استخدم ، على سبيل المثال ، bufio (هناك كل شيء محدد). أو افعل ما قلته للتو: قارئ بروكسي معين ، والذي وفقًا لقائمة المتطلبات الخاصة بك سيتحقق من هذه البيانات وإما إرجاعها إلى العميل أو إعادتها إلى العميل.




القليل من الدعاية :)


أشكركم على البقاء معنا. هل تحب مقالاتنا؟ هل تريد رؤية مواد أكثر إثارة للاهتمام؟ ادعمنا عن طريق تقديم طلب أو التوصية لأصدقائك VPS القائم على السحابة للمطورين من $ 4.99 ، وهو نظير فريد من نوعه لخوادم مستوى الدخول التي اخترعناها لك: الحقيقة الكاملة عن VPS (KVM) E5-2697 v3 (6 نوى) 10GB DDR4 480GB SSD 1Gbps من $ 19 أو كيفية تقسيم الخادم؟ (تتوفر الخيارات مع RAID1 و RAID10 ، حتى 24 مركزًا و 40 جيجابايت DDR4).

Dell R730xd أرخص مرتين في مركز بيانات Equinix Tier IV في أمستردام؟ فقط لدينا 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV من 199 دولارًا في هولندا!Dell R420 - 2x E5-2430 2.2 جيجا هرتز 6C 128 جيجا بايت DDR3 2x960GB SSD 1Gbps 100TB - من 99 دولار! اقرأ عن كيفية بناء مبنى البنية التحتية الفئة c باستخدام خوادم Dell R730xd E5-2650 v4 بتكلفة 9000 يورو مقابل سنت واحد؟

All Articles