Changing a slice's entry that contains Struct Objects

Hello Everyone

I’m trying to set up a Function, that is taking a slice, that is containing a struct, that should change a variable that is saved in this Struct, which then is written into a CSV File. Now unfortunately it does not adjust the variable’s value globally, but only in the function (I hope I explained everything correctly, I am fairly new to GoLang and Programming^^).

Here is the struct i am talking about:

// Contact as type, consists of different strings
type Contact struct {
	ID        string
	FirstName string
	LastName  string
	Title     string
	EMail     string
}

And the slice of the “Object”-Struct Type:

var contacts []Contact

And here’s the function on how to change a specific entry in the struct (No Idea if that is correct in any way^^)

func EditContact(selection string, toEditValue string, EditValue string) {
	//var tempContacts []Contact
	//var contactsFound = false
	fmt.Println("Im in this function")
	switch {

	case selection == "id":
		
		for _, contact := range contacts {

			
			if contact.ID == toEditValue {
				//contactsFound = true
				
				contact.ID = EditValue
				fmt.Println("The ID is now", contact.ID)

			}

		}
		if filePersistence {

			updateDataInFile()
		} else {
		
		}
		break
	case selection == "fn":
		break
	case selection == "ln":
		break
	case selection == "jt":
		break
	case selection == "em":
		break

	}

}

And here’s the function that is writing the content into the CSV-File

func updateDataInFile() {
	//Open Afile and add with O_Trunc the new lines, 0755 are the permissions to edit the file
	file, err := os.OpenFile(FileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
	checkError("Cannot open file", err)
	writer := csv.NewWriter(file)
	//This for loop writes the new contacts line by line
	for _, contact := range contacts {
		contactSerialized := []string{contact.ID, contact.FirstName, contact.LastName, contact.Title, contact.EMail}
		err := writer.Write(contactSerialized)
		checkError("Cannot write to file", err)
		fmt.Println("udpatedatainfile here. contact.ID is now", contact.ID)
	}

	writer.Flush()
	file.Close()
}

My guess is that I would need to return it…but that was not necessary for deleting entries:

func DeleteContact(id string) {

	//Temporary slice to add an empty entry, forward the index back by one
	var tempContacts []Contact
	var contactsFound = false
	for _, contact := range contacts {
		if contact.ID == id {
			contactsFound = true
		} else {
			tempContacts = append(tempContacts, contact)
		}
	}

	if contactsFound {
		contacts = tempContacts
	}
	//write the new data into file
	if filePersistence {
		updateDataInFile()
	}

}

Can you tell me what I’m doing wrong?

Thank you for your help.

Kind regards,

Gabe

The problem is that “contact” in function is a local copy. That the reason you see the changes but not in contacts. Chane this code:

for _, contact := range contacts {
  if contact.ID == toEditValue {
     contactsFound = true
      contact.ID = EditValue
      fmt.Println("The ID is now", contact.ID)
  }   
}

To

  for i := 0; i < len(contacts); i++ {
	    if contacts[i].ID == toEditValue {
		    contactsFound = true
		    contacts[i].ID = EditValue
		    fmt.Println("The ID is now", contacts[i].ID)
            break
	     }
   }
2 Likes

Dear Yamil_Bracho

Thanks, this worked! Can you explain to me what exactly “chane this code” means?

Kind regards,

Gabe

jejej, sorry!! a typo!!! it should be “change this code” :grinning:

Ooooh^^, sorry i genuinely wasn’t sure what you meant.

So just to be sure I got this correct: this is not a local copy anymore, because we are now looping through the index of the correct Struct?

Thank you for your help.

Cheers,

Gabe

Yes. You are using now the original object no a copy…

An alternative is to use a []*Contact. Then the contact in the original loop is a pointer to the Contact, and assigning to its field changes the original Contact object.