আপনি কীভাবে কোনও টুকরো পরিষ্কার করবেন?


125

গোতে কোনও টুকরো পরিষ্কার করার উপযুক্ত উপায় কী?

গো ফোরামে আমি যা পেয়েছি তা এখানে :

// test.go
package main

import (
    "fmt"
)

func main() {
    letters := []string{"a", "b", "c", "d"}
    fmt.Println(cap(letters))
    fmt.Println(len(letters))
    // clear the slice
    letters = letters[:0]
    fmt.Println(cap(letters))
    fmt.Println(len(letters))
}

এটা কি সঠিক?

স্পষ্ট করতে, বাফার সাফ করা হয়েছে যাতে এটি পুনরায় ব্যবহার করা যায়।

বাইটস প্যাকেজটিতে বাফার.আর ট্রান্সকেট ফাংশনটির একটি উদাহরণ ।

লক্ষ্য করুন যে রিসেটটি কেবল ট্রানসেটকে (0) কল করে। সুতরাং দেখা যাচ্ছে যে এই ক্ষেত্রে 70 টি লাইন মূল্যায়ন করবে: b.buf = b.buf [0: 0]

http://golang.org/src/pkg/bytes/buffer.go

// Truncate discards all but the first n unread bytes from the buffer.
60  // It panics if n is negative or greater than the length of the buffer.
61  func (b *Buffer) Truncate(n int) {
62      b.lastRead = opInvalid
63      switch {
64      case n < 0 || n > b.Len():
65          panic("bytes.Buffer: truncation out of range")
66      case n == 0:
67          // Reuse buffer space.
68          b.off = 0
69      }
70      b.buf = b.buf[0 : b.off+n]
71  }
72  
73  // Reset resets the buffer so it has no content.
74  // b.Reset() is the same as b.Truncate(0).
75  func (b *Buffer) Reset() { b.Truncate(0) }

1
একটি দ্রুত পরীক্ষা: play.golang.org/p/6Z-qDQtpbg দেখে মনে হয় যে এটি কাজ করবে (সক্ষমতা পরিবর্তন করবে না তবে এটি দৈর্ঘ্য কেটে দেবে)
জেসন স্পারস্ক

উত্তর:


120

এটি সমস্ত 'পরিষ্কার' এর সংজ্ঞা আপনার উপর নির্ভর করে। বৈধ একটি অবশ্যই হ'ল:

slice = slice[:0]

কিন্তু একটি ধরা আছে। যদি স্লাইস উপাদানগুলি টি টাইপের হয়:

var slice []T

তারপরে len(slice)উপরের "কৌতুক" দ্বারা শূন্য হতে বলপূর্বক কোনও উপাদান তৈরি করে না

slice[:cap(slice)]

আবর্জনা সংগ্রহের জন্য যোগ্য। এটি কিছু পরিস্থিতিতে সর্বোত্তম পন্থা হতে পারে। তবে এটি "মেমরি ফাঁস" - এর একটি কারণও হতে পারে - মেমরিটি ব্যবহার করা হয় না, তবে সম্ভাব্যভাবে পৌঁছানো যায় ('স্লাইস' পুনরায় কাটানোর পরে) এবং এইভাবে আবর্জনা "সংগ্রহযোগ্য" না।


1
মজাদার. অন্তর্নিহিত ক্ষমতাটি অপরিবর্তিত রেখে স্লাইসের অন্তর্নিহিত অ্যারে থেকে সমস্ত উপাদানগুলি সরানোর অন্য কোনও উপায় আছে কি?
ক্রিস ওয়েবার

3
@ ক্রিস ওয়েবার: অন্তর্নিহিত অ্যারেটি দিয়ে কেবল পুনরাবৃত্তি করুন এবং সমস্ত উপাদানকে একটি নতুন মান হিসাবে সেট করুন
newacct

2
@ জেএনএমএল, আমি স্লাইসটি (এবং অন্তর্নিহিত অ্যারে স্টোরেজ) পুনরায় ব্যবহার করতে চাই তাই আমি ক্রমাগতভাবে একটি নতুন স্লাইস বরাদ্দ করছি না (অ্যারে সহ)। আমি আমার প্রশ্নটি স্পষ্ট করতে এবং আদর্শ লাইব্রেরি থেকে উদাহরণ উদাহরণ দেখানোর জন্য সম্পাদনা করেছি।
ক্রিস ওয়েবার

1
আমি যেতে নতুন। আপনি দয়া করে কেন এটি সর্বোত্তম পদ্ধতির হতে পারে সে সম্পর্কে আরও ব্যাখ্যা করতে পারেন? আগাম ধন্যবাদ.
সাতোরু

আপনি কি নিশ্চিত যে ফালি আকার রিসেট মেমরি ফাঁসের কারণ? আমি এটি পুনরুত্পাদন করতে সক্ষম নই
টমমসো বারবুগলি

197

স্লাইস সেট করা কোনও স্লাইস nilসাফ করার সেরা উপায়। nilচলতে থাকা স্লাইসগুলি পুরোপুরি ভাল আচরণ করা হয়েছে এবং nilআবর্জনা সংগ্রহকারীকে অন্তর্নিহিত মেমরিটি মুক্তি দেবে যাতে স্লাইস সেট করে ।

খেলার মাঠ দেখুন

package main

import (
    "fmt"
)

func dump(letters []string) {
    fmt.Println("letters = ", letters)
    fmt.Println(cap(letters))
    fmt.Println(len(letters))
    for i := range letters {
        fmt.Println(i, letters[i])
    }
}

func main() {
    letters := []string{"a", "b", "c", "d"}
    dump(letters)
    // clear the slice
    letters = nil
    dump(letters)
    // add stuff back to it
    letters = append(letters, "e")
    dump(letters)
}

ছাপে

letters =  [a b c d]
4
4
0 a
1 b
2 c
3 d
letters =  []
0
0
letters =  [e]
1
1
0 e

নোট করুন যে টুকরোগুলি সহজেই aliised করা যায় যাতে দুটি টুকরা একই অন্তর্নিহিত মেমরিতে নির্দেশ করে। সেটিংটি nilসেই এলিয়াসিং সরিয়ে ফেলবে।

এই পদ্ধতিটি যদিও ক্ষমতাটিকে শূন্যে পরিবর্তন করে।


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

আমি যা অনুসন্ধান করেছি এটিই!)
তৈমুর ফয়েজরাখমানভ

5
"আপনি কীভাবে একটি টুকরো সাফ করবেন?" শিরোনামের উপর ভিত্তি করে এটি এখন পর্যন্ত আরও নিরাপদ উত্তর এবং এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। একটি নিখুঁত উত্তর হ'ল মূলত গৃহীত উত্তরগুলির সংমিশ্রণ এবং এটি একটি যাতে লোকেরা নিজেরাই সিদ্ধান্ত নিতে পারে, যদিও।
শাদোনিনজা

1
appendএকটি nilস্লাইসে আইএনজি সর্বদা গোতে কাজ করেছেন?
আলেডিয়াফেরিয়া

@aleiaferia যেহেতু অবশ্যই 1.0 যান।
নিক ক্রেগ-উড

4

আমি আমার নিজের উদ্দেশ্যে এই বিষয়টিকে কিছুটা তাকাচ্ছিলাম; আমার স্ট্রাইকগুলির একটি টুকরো ছিল (কিছু পয়েন্টার সহ) এবং আমি নিশ্চিত করতে চাই যে আমি এটি সঠিকভাবে পেয়েছি; এই থ্রেডে শেষ হয়েছে এবং আমার ফলাফলগুলি ভাগ করতে চেয়েছিল।

অনুশীলন করতে, আমি খেলার মাঠে কিছুটা এগিয়ে গিয়েছিলাম: https://play.golang.org/p/9i4gPx3lnY

যা এটি প্রমাণ করে:

package main

import "fmt"

type Blah struct {
    babyKitten int
    kittenSays *string
}

func main() {
    meow := "meow"
    Blahs := []Blah{}
    fmt.Printf("Blahs: %v\n", Blahs)
    Blahs = append(Blahs, Blah{1, &meow})
    fmt.Printf("Blahs: %v\n", Blahs)
    Blahs = append(Blahs, Blah{2, &meow})
    fmt.Printf("Blahs: %v\n", Blahs)
    //fmt.Printf("kittenSays: %v\n", *Blahs[0].kittenSays)
    Blahs = nil
    meow2 := "nyan"
    fmt.Printf("Blahs: %v\n", Blahs)
    Blahs = append(Blahs, Blah{1, &meow2})
    fmt.Printf("Blahs: %v\n", Blahs)
    fmt.Printf("kittenSays: %v\n", *Blahs[0].kittenSays)
}

সেই কোডটি যেমন রয়েছে তেমন চালানো "মেও" এবং "মায়ো 2" ভেরিয়েবল উভয়ের জন্য একই মেমরি ঠিকানাটি দেখায়:

Blahs: []
Blahs: [{1 0x1030e0c0}]
Blahs: [{1 0x1030e0c0} {2 0x1030e0c0}]
Blahs: []
Blahs: [{1 0x1030e0f0}]
kittenSays: nyan

যা আমি মনে করি এটি নিশ্চিত করে যে স্ট্রাক্টটি আবর্জনা সংগ্রহ করা। অদ্ভুতভাবে যথেষ্ট, মন্তব্য করা মুদ্রণ লাইনটি আপত্তিহীন করে মায়াবীদের জন্য বিভিন্ন মেমরি ঠিকানা দেবে:

Blahs: []
Blahs: [{1 0x1030e0c0}]
Blahs: [{1 0x1030e0c0} {2 0x1030e0c0}]
kittenSays: meow
Blahs: []
Blahs: [{1 0x1030e0f8}]
kittenSays: nyan

আমি মনে করি এটি মুদ্রণটি কোনও উপায়ে (?) স্থগিত হওয়ার কারণে হতে পারে তবে কিছু মেমরি এমজিএমটি আচরণের আকর্ষণীয় চিত্র, এবং এর জন্য আরও একটি ভোট:

[]MyStruct = nil

সুন্দর বিস্তারিত উদাহরণ। ধন্যবাদ!
ডোলানর

2
এটি meo1 এবং meow2 এর মেমরি ঠিকানাগুলি একই হিসাবে দেখায় 0x1030e0c0না: এর সমান নয় 0x1030e0f0(পূর্বের প্রান্তটি c0শেষের দিকে f0)।
carbocation

এখানে @ কার্বোকারেশনের সাথে একমত হতে পেরেছি, সেই মেমরির ঠিকানাগুলি এক নয়। আমি এখানে কী ঘটছে তা আরও ভালভাবে ব্যাখ্যা করতে সক্ষম হওয়ার দাবি করি না, তবে এটি আমার পক্ষে প্রমাণ হিসাবে কাজ করে না। আমি meow2প্রতিটি রানের ঠিকানায় একই 8-বাইটের
স্বতন্ত্রতা দেখতে পাচ্ছি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.