2013-09-02 11 views
9

गो पर एक विधि को कॉल करके किसी टुकड़े से किसी आइटम को कैसे निकालें, मुझे फिर से स्टंप कर दिया गया है। उम्मीद है कि कोई मदद कर सकता है। मैंने एक टुकड़ा (MySlice) बनाया है जिसमें structs (myStruct) के पॉइंटर्स शामिल हैं।टुकड़ा

समस्या "निकालें" विधि है। जब हम "निकालें" के अंदर होते हैं तो सब कुछ ठीक है, लेकिन एक बार जब हम वापस आते हैं, तो टुकड़ा आकार बदल नहीं जाता है, और इसलिए हम अंतिम तत्व को दो बार सूचीबद्ध करते हैं।

मैंने मूल रूप से "जोड़ें" विधि में उपयोग किए गए समान पैटर्न का उपयोग करके "निकालें" लिखने का प्रयास किया, लेकिन यह संकलित नहीं होगा और टिप्पणी की गई है।

मैं इसे नए बनाए गए टुकड़े को कॉलिंग फ़ंक्शन पर लौटकर काम करने के लिए प्राप्त कर सकता हूं, लेकिन मैं ऐसा नहीं करना चाहता क्योंकि mySlice (ms) एक सिंगलटन है।

और अगर मैं पहले से ही पर्याप्त ...

"जोड़ें" विधि के लिए कोड काम कर रहा है, हालांकि मुझे यकीन है कि कैसे नहीं कर रहा हूँ के लिए नहीं कहा था। जो मैं इकट्ठा कर सकता हूं उससे "ऐड" स्लाइस हेडर (3 आइटम "स्ट्रक्चर") में पॉइंटर प्राप्त कर रहा है। जो मैंने पढ़ा है, उससे एक टुकड़ा की लंबाई और क्षमता विधियों (जब मूल्य से गुजरती है) को पारित नहीं होती है, तो शायद टुकड़े को पॉइंटर पास करने से विधि को देखने और लंबाई और क्षमता का उपयोग करने की अनुमति मिलती है जिससे हमें अनुमति मिलती है जोड़ने के लिए"। यदि यह सत्य है, तो एक ही पैटर्न "निकालें" में क्यों काम नहीं करता है?

सभी की अंतर्दृष्टि और सहायता के लिए बहुत बहुत धन्यवाद!

package main 

import (
    "fmt" 
) 

type myStruct struct { 
    a int 
} 
type mySlice []*myStruct 

func (slc *mySlice) Add(str *myStruct) { 
    *slc = append(*slc, str) 
} 

//does not compile with reason: cannot slice slc (type *mySlice) 
//func (slc *mySlice) Remove1(item int) { 
// *slc = append(*slc[:item], *slc[item+1:]...) 
//} 

func (slc mySlice) Remove(item int) { 
    slc = append(slc[:item], slc[item+1:]...) 
    fmt.Printf("Inside Remove = %s\n", slc) 
} 

func main() { 
    ms := make(mySlice, 0) 
    ms.Add(&myStruct{0}) 
    ms.Add(&myStruct{1}) 
    ms.Add(&myStruct{2}) 
    fmt.Printf("Before Remove: Len=%d, Cap=%d, Data=%s\n", len(ms), cap(ms), ms) 
    ms.Remove(1) //remove element 1 (which also has a value of 1) 
    fmt.Printf("After Remove: Len=%d, Cap=%d, Data=%s\n", len(ms), cap(ms), ms) 
} 

और परिणाम ...

Before Remove: Len=3, Cap=4, Data=[%!s(*main.myStruct=&{0}) %!s(*main.myStruct=&{1}) %!s(*main.myStruct=&{2})] 

Inside Remove = [%!s(*main.myStruct=&{0}) %!s(*main.myStruct=&{2})] 

After Remove: Len=3, Cap=4, Data=[%!s(*main.myStruct=&{0}) %!s(*main.myStruct=&{2}) %!s(*main.myStruct=&{2})] 

उत्तर

12

आप सही Remove1() के साथ पहली बार थे। निकालें टुकड़ा की एक प्रति प्राप्त करता है और इसलिए टुकड़ा की लंबाई नहीं बदल सकता है।

आपके निकालने के कार्य में यह मुद्दा यह है कि गो में संचालन के क्रम में, स्लाइसिंग डीरफ्रेंसिंग से पहले आता है।

फिक्स *slc = append(*slc[:item], *slc[item+1:]...) से *slc = append((*slc)[:item], (*slc)[item+1:]...) को बदलने का है।

हालांकि मैं पठनीयता और रख-रखाव के लिए निम्नलिखित की सिफारिश करेंगे:

func (slc *mySlice) Remove1(item int) { 
    s := *slc 
    s = append(s[:item], s[item+1:]...) 
    *slc = s 
} 
+0

धन्यवाद अपने त्वरित जवाब स्टीफन लिए बहुत-बहुत! तो बस स्पष्ट करने के लिए, जब कार्यों/विधियों में स्लाइस पास करते हैं तो केवल एक चीज जो कभी पारित हो जाती है वह टुकड़ा की 3-वस्तु संरचना परिभाषा (कभी अंतर्निहित सरणी नहीं) होती है। मूल्य से गुजरते समय मैं स्लाइस परिभाषा की एक प्रति गुजर रहा हूं और वरीयता से गुज़रने पर मैं स्लाइस परिभाषा के लिए एक सूचक पास कर रहा हूं? एक बार फिर धन्यवाद! – user2736464

+0

सही। जब आप कोई मान पास करते हैं, तो आपको स्लाइस के लेन, टोपी और बैकिंग सरणी में पॉइंटर की एक प्रति प्राप्त होती है। जब आप स्लाइस पर पॉइंटर पास करते हैं, तो आप मूल के लेन और टोपी को संशोधित कर सकते हैं। –

1

क्योंकि संलग्न जरूरी टुकड़ा के संदर्भ में एक ही पते के लिए वापस नहीं होगा के रूप में स्टीफन वेनबर्ग ने कहा है। इस सीमा के साथ काम करने का एक और तरीका स्लाइस को लपेटने वाली संरचना को परिभाषित करना है।

उदाहरण के लिए:

package main 

import "fmt" 

type IntList struct { 
    intlist []int 
} 

func (il *IntList) Pop() { 
    if len(il.intlist) == 0 { return } 
    il.intlist = il.intlist[:len(il.intlist)-1] 
} 

func (il *IntList) Add(i... int) { 
    il.intlist = append(il.intlist, i...) 
} 

func (il *IntList) String() string { 
    return fmt.Sprintf("%#v",il.intlist) 
} 

func main() { 
    intlist := &IntList{[]int{1,2,3}} 
    fmt.Println(intlist) 
    intlist.Pop() 
    fmt.Println(intlist) 
    intlist.Add([]int{4,5,6}...) 
    fmt.Println(intlist) 
} 

उत्पादन:

[]int{1, 2, 3} 
[]int{1, 2} 
[]int{1, 2, 4, 5, 6} 
संबंधित मुद्दे