5
\$\begingroup\$

I have an application with a recent addition that requires the removal of a struct pointer from a slice that is itself an element of another struct. A summary of the usage.

I am wondering if this is idiomatic and okay usage of the go languages. Things appear to work and this appears to be inline with the golang recommendations for slice element deletion.

package main
import (
 "fmt"
 "strconv"
)
const ARBITRARY= 5
type myData struct {
 det detailSlicePtr 
}
type detail struct {
 id int
 name string
}
// Slice of pointers to details
type detailSlicePtr []*detail
// Returns true if item removed succesfully,
// false all other cases
func(s *myData ) remove(d *detail) bool {
 for i:= range s.det {
 if s.det[i].name == d.name && s.det[i].id == d.id {
 s.det[i] = new(detail)
 s.det = append(s.det[:i],s.det[i+1:]...)
 return true
 }
 }
 return false
}
// Find and remove a struct element from a slice of struct pointers within a struct
func main() {
 var d myData
 details := make(detailSlicePtr , ARBITRARY)
 for j := 0; j < ARBITRARY; j++ {
 details [j] = &detail{
 id: j,
 name: strconv.Itoa(j),
 }
 }
 d.det = details 
 // Print out what we have so far
 for index := range d.det {
 fmt.Printf("Item %d is %s\n", index, d.det[index].name)
 }
 findMe := ARBITRARY / 2
 middle := &detail{id: findMe ,name:strconv.Itoa(findMe)}
 if ok := d.remove(middle); !ok {
 fmt.Printf("Unable to find element: %v\n", middle)
 } else {
 fmt.Printf("Found and removed element: %v\n", middle)
 // Print what is left
 for index := range d.det {
 fmt.Printf("Item %d is %s\n", index, d.det[index].name)
 } 
 }
}
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Jan 24, 2015 at 1:19
\$\endgroup\$
0

1 Answer 1

5
\$\begingroup\$

It is not idiomatic and it is not okay usage. It should be:

SliceTricks

Delete (pointers)

copy(a[i:], a[i+1:])
a[len(a)-1] = nil // or the zero value of T
a = a[:len(a)-1]

For example,

package main
import (
 "fmt"
 "strconv"
)
const ARBITRARY = 5
type myData struct {
 det detailSlicePtr
}
type detail struct {
 id int
 name string
}
// Slice of pointers to details
type detailSlicePtr []*detail
// Returns true if item removed succesfully,
// false all other cases
func (s *myData) remove(d *detail) bool {
 for i := range s.det {
 if s.det[i].name == d.name && s.det[i].id == d.id {
 copy(s.det[i:], s.det[i+1:])
 s.det[len(s.det)-1] = nil
 s.det = s.det[:len(s.det)-1]
 return true
 }
 }
 return false
}
// Find and remove a struct element from a slice of struct pointers within a struct
func main() {
 var d myData
 details := make(detailSlicePtr, ARBITRARY)
 for j := 0; j < ARBITRARY; j++ {
 details[j] = &detail{
 id: j,
 name: strconv.Itoa(j),
 }
 }
 d.det = details
 // Print out what we have so far
 for index := range d.det {
 fmt.Printf("Item %d is %s\n", index, d.det[index].name)
 }
 // Print what is hidden
 for i := range d.det[len(d.det):cap(d.det)] {
 j := len(d.det) + i
 det := d.det[:cap(d.det)]
 fmt.Printf("Hidden item %d is %v\n", j, det[j])
 }
 findMe := ARBITRARY / 2
 middle := &detail{id: findMe, name: strconv.Itoa(findMe)}
 if ok := d.remove(middle); !ok {
 fmt.Printf("Unable to find element: %v\n", middle)
 } else {
 fmt.Printf("Found and removed element: %v\n", middle)
 // Print what is left
 for index := range d.det {
 fmt.Printf("Item %d is %s\n", index, d.det[index].name)
 }
 // Print what is hidden
 for i := range d.det[len(d.det):cap(d.det)] {
 j := len(d.det) + i
 det := d.det[:cap(d.det)]
 fmt.Printf("Hidden item %d is %v\n", j, det[j])
 }
 }
}

Output:

Item 0 is 0
Item 1 is 1
Item 2 is 2
Item 3 is 3
Item 4 is 4
Found and removed element: &{2 2}
Item 0 is 0
Item 1 is 1
Item 2 is 3
Item 3 is 4
Hidden item 4 is <nil>

NOTE: There is a bug in the Slice Tricks that you linked to. It will be corrected soon. Until then use the link in my answer.

answered Jan 24, 2015 at 19:37
\$\endgroup\$
1
  • \$\begingroup\$ Awesome, thank you. So just to check my understanding: In the remove method, use copy to basically push our element to the end, nil that index, assign our struct field to the new slice that is now 1 element shorter. So this frees the memory consumed by the target element, and shrinks our slice by 1, correct? I'm not sure how the show hidden loop is not causing a panic here. \$\endgroup\$ Commented Jan 24, 2015 at 20:15

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.