Io.Reader থেকে Go এ স্ট্রিং পর্যন্ত


129

আমার একটি io.ReadCloserবস্তু আছে (একটি http.Responseবস্তু থেকে )।

পুরো স্ট্রিমটিকে কোনও stringবস্তুতে রূপান্তর করার সবচেয়ে কার্যকর উপায় কোনটি ?

উত্তর:


175

সম্পাদনা করুন:

১.১০ সাল থেকে স্ট্রিংস.বিল্ডার বিদ্যমান। উদাহরণ:

buf := new(strings.Builder)
n, err := io.Copy(buf, r)
// check errors
fmt.Println(buf.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))

আমরা সেখানে যাই, আপনি এখন দক্ষতার সাথে আপনার বাইট অ্যারে স্ট্রিংয়ে রূপান্তর করেছেন। সত্যিই, এই সমস্ত কাজটি টাইপ সিস্টেমটিকে স্ট্রিং হিসাবে কল্পনা করে। এই পদ্ধতিতে কয়েকটি দম্পতি রয়েছে:

  1. এটি কোনও গো সংস্থাপকগুলিতে কাজ করবে এমন কোনও গ্যারান্টি নেই। যদিও এটি পরিকল্পনা -9 গিসি সংকলকটির সাথে কাজ করে, এটি "বাস্তবায়নের বিশদগুলিতে" নির্ভর করে যা সরকারী অনুমানে উল্লিখিত হয়নি। এমনকি আপনি গ্যারান্টিও দিতে পারবেন না যে এটি সমস্ত আর্কিটেকচারে কাজ করবে বা সিসিতে পরিবর্তন হবে না। অন্য কথায়, এটি একটি খারাপ ধারণা।
  2. যে স্ট্রিং পরিবর্তনীয়! আপনি যদি সেই বাফারটিতে কোনও কল করেন তবে তা স্ট্রিং পরিবর্তন করবে । খুব সতর্ক হও.

আমার পরামর্শটি সরকারী পদ্ধতিতে লেগে থাকা। অনুলিপি করা এত ব্যয়বহুল নয় এবং এটি অনিরাপদগুলির কুফলের জন্য মূল্যবান নয়। যদি স্ট্রিংটি অনুলিপি করার জন্য খুব বড় হয় তবে আপনার এটি স্ট্রিং হিসাবে তৈরি করা উচিত নয়।


ধন্যবাদ, এটি একটি সত্যই উত্তর। "ভাল" উপায়টি মোটামুটি @ সোনার জবাবের সমান বলে মনে হয় (যেহেতু বুফ। স্ট্রিং কেবল অভ্যন্তরীণভাবে কাস্ট করে)।
ডিজেডি

1
এবং এটি আমার সংস্করণেও কাজ করে না, মনে হয় যে এটি & but.Bytes () থেকে কোনও পয়েন্টার পেতে সক্ষম হবে না। Go1 ব্যবহার করে।
sinni800

@ sinni800 টিপটির জন্য ধন্যবাদ। আমি ভুলে গিয়েছিলাম ফাংশন রিটার্নগুলি ঠিকানাযোগ্য নয়। এটা এখন স্থির।
স্টিফেন ওয়েনবার্গ

3
ওয়েল কম্পিউটারগুলি বাইটগুলির ব্লকগুলি অনুলিপি করার জন্য খুব খারাপ are এবং প্রদত্ত এটি একটি এইচটিপি অনুরোধ, আমি এমন দৃশ্যের কল্পনাও করতে পারি না যেখানে বাইট অ্যারের অনুলিপি করার ক্ষেত্রে সংক্ষিপ্ত সময়ের তুলনায় তুচ্ছ সময়ের চেয়ে স্ক্রিলিয়ন গুণ বড় হবে না। যে কোনও কার্যনির্বাহী ভাষা এই জায়গার চারপাশে এই ধরণের অপরিবর্তনীয় জিনিসগুলি অনুলিপি করে এবং এখনও প্রচুর দ্রুত চলে।
আরও তীক্ষ্ণ দেখুন

এই উত্তরটি পুরানো। strings.Builderঅন্তর্নিহিত []byteকখনই ফাঁস হয় না তা নিশ্চিত করে এবং stringএইভাবে কোনও কপি ছাড়াই এমনভাবে রূপান্তর করে যাতে এগিয়ে যাওয়া সমর্থনযোগ্য। এটি ২০১২ সালে উপস্থিত ছিল না @ একটি সম্পাদনা বিবেচনা করুন!
নুনো ক্রুস

102

উত্তরগুলি এখনও পর্যন্ত প্রশ্নের পুরো অংশটিকে "সম্বোধন" করতে পারেনি। আমি মনে করি এটি করার ভাল উপায় ioutil.ReadAll। আপনার io.ReaderCloserনাম দিয়ে rcআমি লিখব,

if b, err := ioutil.ReadAll(rc); err == nil {
    return string(b)
} ...

2
ধন্যবাদ, ভাল উত্তর। দেখে মনে হচ্ছে buf.ReadFrom()ইওএফ পর্যন্ত পুরো স্ট্রিমটি পড়েছে।
ডিজেডি

8
কী মজার: আমি কেবল বাস্তবায়নটি পড়েছি ioutil.ReadAll()এবং এটি কেবল একটি bytes.Buffer'র' জড়িয়ে দেয় ReadFrom। এবং বাফারের String()পদ্ধতিটি কাস্টিংয়ের চারপাশে একটি সহজ মোড়ক string- সুতরাং দুটি পদ্ধতির ব্যবহারিকভাবে একই রকম!
ডিজেডি

1
এটি সেরা, সবচেয়ে সংক্ষিপ্ত সমাধান।
এম কে 12

1
আমি এটি করেছি এবং এটি কাজ করে ... প্রথমবার। স্ট্রিং পড়ার পরে কোনও কারণে, পরবর্তী পাঠগুলি একটি খালি স্ট্রিং ফেরত দেয়। এখনও নিশ্চিত না কেন।
আলডো 'xoen' গিয়ামেলুকা

1
@ অ্যালডো'কসোয়েন'গিয়ামেলুকা রিডআল পাঠককে গ্রাস করে, তাই পরবর্তী কলটিতে পড়ার মতো কিছুই অবশিষ্ট নেই।
ড্যানজেজে


5

সবচেয়ে কার্যকর উপায় হ'ল []byteপরিবর্তে সর্বদা ব্যবহার করা string

আপনার কাছ থেকে প্রাপ্ত ডেটা মুদ্রণের প্রয়োজন io.ReadCloserহলে fmtপ্যাকেজটি পরিচালনা করতে পারে []byteতবে এটি কার্যকর নয় কারণ fmtপ্রয়োগটি অভ্যন্তরীণভাবে রূপান্তরিত []byteহবে string। এই রূপান্তরটি এড়ানোর জন্য, আপনি fmt.Formatterকোনও ধরণের জন্য ইন্টারফেসটি প্রয়োগ করতে পারেন type ByteSlice []byte


[] বাইট থেকে স্ট্রিংয়ে রূপান্তর কি ব্যয়বহুল? আমি ধরে নিয়েছি স্ট্রিং ([] বাইট) আসলে [] বাইটটি অনুলিপি করেনি, তবে কেবল স্লাইস উপাদানগুলিকে রানসের সিরিজ হিসাবে ব্যাখ্যা করেছেন। এজন্য আমি বাফার.স্ট্রিং () সাপ্তাহিক . golang.org/src/pkg/bytes/buffer.go?s=1787:1819#L37 পরামর্শ দিয়েছি । আমার ধারণা, যখন স্ট্রিং ([] বাইট) বলা হয় তখন কী হয় তা জেনে রাখা ভাল হবে।
নট

4
থেকে রূপান্তর []byteকরতে stringযুক্তিসঙ্গতভাবে দ্রুত, কিন্তু প্রশ্ন "সবচেয়ে কার্যকর উপায়" সম্পর্কে জিজ্ঞাসা ছিল। বর্তমানে, গো রান-টাইম stringরূপান্তরিত []byteহওয়ার সময় সর্বদা একটি নতুন বরাদ্দ করবে string। এর কারণ হ'ল সংকলক []byteরূপান্তরতার পরে কীভাবে পরিবর্তন করা হবে তা নির্ধারণ করতে জানে না । সংকলক অপ্টিমাইজেশনের জন্য এখানে কিছু জায়গা রয়েছে।

3
func copyToString(r io.Reader) (res string, err error) {
    var sb strings.Builder
    if _, err = io.Copy(&sb, r); err == nil {
        res = sb.String()
    }
    return
}


0

আমি বাইটস.বাফার স্ট্রাক্ট পছন্দ করি । আমি দেখতে পাচ্ছি এটিতে ReadFrom এবং স্ট্রিং পদ্ধতি রয়েছে। আমি এটি একটি [] বাইট দিয়ে ব্যবহার করেছি তবে আইও.আরডিডার নয়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.