में स्ट्रिंग करने के लिए io.Reader से मेरे पास io.ReadCloser
ऑब्जेक्ट है (http.Response
ऑब्जेक्ट से)।गो
संपूर्ण स्ट्रीम को string
ऑब्जेक्ट में परिवर्तित करने का सबसे प्रभावी तरीका क्या है?
में स्ट्रिंग करने के लिए io.Reader से मेरे पास io.ReadCloser
ऑब्जेक्ट है (http.Response
ऑब्जेक्ट से)।गो
संपूर्ण स्ट्रीम को string
ऑब्जेक्ट में परिवर्तित करने का सबसे प्रभावी तरीका क्या है?
संक्षिप्त उत्तर यह है कि यह कुशल नहीं होगा क्योंकि स्ट्रिंग में कनवर्ट करने से बाइट सरणी की पूरी प्रतिलिपि की आवश्यकता होती है। आप जो चाहते हैं उसे करने के लिए उचित (गैर-कुशल) तरीका यहां दिया गया है:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
s := buf.String() // Does a complete copy of the bytes in the buffer.
यह प्रति सुरक्षा तंत्र के रूप में की जाती है। स्ट्रिंग्स अपरिवर्तनीय हैं। यदि आप एक [] बाइट को एक स्ट्रिंग में परिवर्तित कर सकते हैं, तो आप स्ट्रिंग की सामग्री बदल सकते हैं। हालांकि, आपको असुरक्षित पैकेज का उपयोग करके प्रकार सुरक्षा तंत्र को अक्षम करने की अनुमति देता है। अपने जोखिम पर असुरक्षित पैकेज का प्रयोग करें। उम्मीद है कि अकेले नाम एक अच्छी पर्याप्त चेतावनी है। यहाँ कैसे मैं असुरक्षित का उपयोग कर इसे करना होगा है:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
b := buf.Bytes()
s := *(*string)(unsafe.Pointer(&b))
वहाँ हम चले, अब आप कुशलता से अपने बाइट सरणी एक स्ट्रिंग में बदल जाती है। असल में, यह सब टाइप सिस्टम को स्ट्रिंग कहने में चाल है। इस विधि में कुछ चेतावनी हैं:
मेरी सलाह आधिकारिक विधि से चिपकना है। एक प्रतिलिपि करना है कि महंगा है और यह असुरक्षित की बुराइयों के लायक नहीं है। यदि स्ट्रिंग करने के लिए स्ट्रिंग बहुत बड़ी है, तो आपको इसे स्ट्रिंग में नहीं बनाना चाहिए।
मुझे bytes.Buffer संरचना पसंद है। मुझे लगता है कि इसमें ReadFrom और String विधियां हैं। मैंने इसे एक [] बाइट के साथ उपयोग किया है लेकिन एक io.Reader नहीं है।
सबसे प्रभावी तरीका के बजाय हमेशा []byte
का उपयोग करना होगा।
मामले में आप io.ReadCloser
से प्राप्त डेटा मुद्रित करने के लिए, fmt
पैकेज []byte
संभाल कर सकते हैं की जरूरत है, लेकिन यह कुशल नहीं है क्योंकि fmt
कार्यान्वयन आंतरिक string
को []byte
परिवर्तित कर देंगे। इस रूपांतरण से बचने के लिए, आप इंटरफेस को type ByteSlice []byte
जैसे प्रकार के लिए कार्यान्वित कर सकते हैं।
स्ट्रिंग महंगा करने से [] बाइट रूपांतरण है? मुझे लगता है कि स्ट्रिंग ([] बाइट) वास्तव में [] बाइट की प्रतिलिपि नहीं बनाई गई थी, लेकिन सिर्फ स्लाइस तत्वों को रनों की श्रृंखला के रूप में व्याख्या की गई थी। यही कारण है कि मैंने बफर। स्ट्रिंग() http://weekly.golang.org/src/pkg/bytes/buffer.go?s=1787:1819#L37 का सुझाव दिया। मुझे लगता है कि स्ट्रिंग ([] बाइट) कहलाते समय क्या हो रहा है यह जानना अच्छा होगा। – Nate
'[] बाइट' से 'स्ट्रिंग' में रूपांतरण काफी तेज़ है, लेकिन सवाल" सबसे प्रभावी तरीका "के बारे में पूछ रहा था। वर्तमान में, 'रन] टाइम' [] बाइट' को 'स्ट्रिंग' में परिवर्तित करते समय हमेशा एक नया 'स्ट्रिंग' आवंटित करेगा। इसका कारण यह है कि संकलक यह नहीं जानता कि रूपांतरण के बाद '[] बाइट' संशोधित किया जाएगा या नहीं। यहां कंपाइलर अनुकूलन के लिए कुछ जगह है। –
उत्तर अब तक इस प्रश्न के "संपूर्ण स्ट्रीम" हिस्से को संबोधित नहीं किया है। मुझे लगता है कि ऐसा करने का अच्छा तरीका ioutil.ReadAll
है। अपने io.ReaderCloser
rc
नामित के साथ, मैं लिखते थे,
if b, err := ioutil.ReadAll(rc); err == nil {
return string(b)
} ...
धन्यवाद, अच्छा जवाब। ऐसा लगता है कि 'buf.ReadFrom()' ईओएफ तक पूरी स्ट्रीम भी पढ़ता है। – djd
कितना हास्यास्पद है: मैंने अभी 'ioutil.ReadAll()' के कार्यान्वयन को पढ़ा है और यह बस 'बाइट्स' बफर 'के' ReadFrom' को लपेटता है। और बफर की 'स्ट्रिंग()' विधि 'स्ट्रिंग' पर कास्टिंग के चारों ओर एक साधारण लपेटो है - इसलिए दो दृष्टिकोण व्यावहारिक रूप से वही हैं! – djd
यह सबसे अच्छा, सबसे संक्षिप्त समाधान है। – mk12
धन्यवाद, यह वास्तव में एक विस्तृत उत्तर है। "अच्छा" तरीका लगभग @ सोनिया के जवाब के बराबर लगता है (चूंकि buf.String केवल आंतरिक रूप से कलाकार करता है)। – djd
और यह मेरे संस्करण के साथ भी काम नहीं करता है, ऐसा लगता है कि यह पॉइंटर प्राप्त करने में सक्षम नहीं है, लेकिन बाइट्स()। Go1 का उपयोग करना। – sinni800
@ sinni800 टिप के लिए धन्यवाद। मैं भूल गया कि रिटर्न रिटर्न एड्रेसेबल नहीं थे। यह अब तय है। –