Golang中如何修改包含结构体对象的切片条目
Golang中如何修改包含结构体对象的切片条目 大家好
我正在尝试设置一个函数,它接收一个包含结构体的切片,该函数应修改保存在此结构体中的变量,然后将其写入CSV文件。但不幸的是,它并未全局调整变量的值,而仅在函数内部生效(希望我的解释是清楚的,我对GoLang和编程还比较陌生^^)。
以下是我提到的结构体:
// Contact 作为类型,由不同的字符串组成
type Contact struct {
ID string
FirstName string
LastName string
Title string
EMail string
}
以及“对象”结构体类型的切片:
var contacts []Contact
以下是修改结构体中特定条目的函数(不确定这样做是否正确^^):
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
}
}
以下是将内容写入CSV文件的函数:
func updateDataInFile() {
//打开文件并使用 O_Trunc 添加新行,0755 是编辑文件的权限
file, err := os.OpenFile(FileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
checkError("Cannot open file", err)
writer := csv.NewWriter(file)
//此 for 循环逐行写入新的联系人
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()
}
我猜测可能需要返回它……但删除条目时并不需要这样做:
func DeleteContact(id string) {
//临时切片用于添加空条目,将索引向前回退一位
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
}
//将新数据写入文件
if filePersistence {
updateDataInFile()
}
}
你能告诉我我做错了什么吗?
感谢你的帮助。
诚挚的问候
更多关于Golang中如何修改包含结构体对象的切片条目的实战教程也可以访问 https://www.itying.com/category-94-b0.html
是的。你正在使用原始对象,而不是一个副本……
更多关于Golang中如何修改包含结构体对象的切片条目的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
哈哈,不好意思!!打错字了!!!应该是“修改这段代码” 😄
亲爱的 Yamil_Bracho
谢谢,这个方法有效!你能向我解释一下“chane this code”具体是什么意思吗?
此致,
Gabe
另一种方法是使用 []*Contact。这样,原始循环中的 contact 就是一个指向 Contact 的指针,对其字段的赋值会改变原始的 Contact 对象。
哦^^,抱歉,我之前确实没太明白您的意思。
那么,为了确认我理解正确:这不再是本地副本了,因为我们现在是在遍历正确结构体的索引,对吗?
感谢您的帮助。
祝好。
问题在于函数中的“contact”是一个局部副本。这就是为什么你看到了变化,但contacts切片中没有变化。将这段代码:
for _, contact := range contacts {
if contact.ID == toEditValue {
contactsFound = true
contact.ID = EditValue
fmt.Println("The ID is now", contact.ID)
}
}
改为:
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
}
}
问题在于你使用了值拷贝的 for range 循环。在 Go 中,for _, contact := range contacts 中的 contact 是切片元素的副本,修改它不会影响原始切片中的结构体。
以下是修正后的代码:
func EditContact(selection string, toEditValue string, EditValue string) {
fmt.Println("Im in this function")
for i := range contacts {
switch selection {
case "id":
if contacts[i].ID == toEditValue {
contacts[i].ID = EditValue
fmt.Println("The ID is now", contacts[i].ID)
}
case "fn":
if contacts[i].FirstName == toEditValue {
contacts[i].FirstName = EditValue
}
case "ln":
if contacts[i].LastName == toEditValue {
contacts[i].LastName = EditValue
}
case "jt":
if contacts[i].Title == toEditValue {
contacts[i].Title = EditValue
}
case "em":
if contacts[i].EMail == toEditValue {
contacts[i].EMail = EditValue
}
}
}
if filePersistence {
updateDataInFile()
}
}
或者使用指针切片:
var contacts []*Contact
func EditContact(selection string, toEditValue string, EditValue string) {
fmt.Println("Im in this function")
for _, contact := range contacts {
switch selection {
case "id":
if contact.ID == toEditValue {
contact.ID = EditValue
fmt.Println("The ID is now", contact.ID)
}
case "fn":
if contact.FirstName == toEditValue {
contact.FirstName = EditValue
}
case "ln":
if contact.LastName == toEditValue {
contact.LastName = EditValue
}
case "jt":
if contact.Title == toEditValue {
contact.Title = EditValue
}
case "em":
if contact.EMail == toEditValue {
contact.EMail = EditValue
}
}
}
if filePersistence {
updateDataInFile()
}
}
DeleteContact 函数能正常工作的原因是它直接操作了 contacts 切片变量,通过重新赋值 contacts = tempContacts 来更新原始切片。

