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