Up to Main Index                              Up to Journal for July, 2012

                      JOURNAL FOR TUESDAY 3RD JULY, 2012
______________________________________________________________________________

SUBJECT: A little slice of faux pas
   DATE: Tue Jul  3 21:30:37 BST 2012

Yet again a large gap in the journal since last time :( So what's been going
on in the meantime?

Coding of the prototype is now mostly done. Documentation is done. Just
finishing off the testing. So far the only faux pas is with slices passed as
parameters - doh! I keep passing and modify the slices. A minor example:


  func New(name string, aliases []string, description string) *Thing {

    for i, a := range aliases {
      aliases[i] = strings.ToUpper(strings.TrimSpace(a))
    }

    t := &Thing{
      name:        name,
      aliases:     aliases,                      // <-- Aliases field
      description: description,
      uniqueId:    <-Next,
      mutex:       make(chan bool, 1),
    }

    return t
  }


Here the aliases parameter is a string slice being passed to the New function.
It is not passed by reference but by value. However the values of a slice are
references to the underlying array elements. What this means is that we cannot
modify the slice itself - length or capacity - but we can modify the array
elements through the slice's references.

In the example above the elements passed in the slice are inadvertently
modified by the calls to ToUpper() and TrimSpace(). The answer to the problem
in this case is quite simple - make a copy of the slice:


  func New(name string, aliases []string, description string) *Thing {

    t := &Thing{
      name:        name,
      aliases:     make([]string, len(aliases)), // <-- Aliases field
      description: description,
      uniqueId:    <-Next,
      mutex:       make(chan bool, 1),
    }

    for i, a := range aliases {
      t.aliases[i] = strings.ToUpper(strings.TrimSpace(a))
    }

    return t
  }


Now we have updated the aliases field - annotated by a comment above in both
listings - in the Thing struct to create a new slice instead of allocating the
passed slice. We have also moved the string manipulation to after the struct
initialisation. This time we do the ToUpper() and TrimSpace() and allocate the
result into the new slice instead of allocating it back to the original slice.

I've also found and corrected a few other corner cases as well. Writing and
testing may take time but it does force you to think more about your code and
pays back the effort every time changes are made and the tests re-run.

--
Diddymus


  Up to Main Index                              Up to Journal for July, 2012