Golang中向结构体映射的切片追加元素时值未设置的解决方案

Golang中向结构体映射的切片追加元素时值未设置的解决方案 我正在尝试向一个结构体中的切片追加字符串,该结构体是映射的一部分。以下是一个展示我所见行为的示例:

package main

import (
	"fmt"
)

type Person struct {
   Userid string
   Nicknames []string
}

var people map[string]Person

func addNickname( person string, nickname string ) {
    	subject := people[person]
    	subject.Nicknames = append( people[person].Nicknames, nickname )
    	fmt.Println("In method - subject: ", subject.Nicknames )
    	fmt.Println("In method - people: ", people[person].Nicknames )
}

func main() {
    	elizabeth := Person{ Userid: "emp01" }
 	people = make(map[string]Person)
    	people["elizabeth"] = elizabeth
    	fmt.Println("People: ", people )

    	addNickname( "elizabeth", "betsy" )
    	fmt.Println("Outside method: ", people["elizabeth"].Nicknames )

    	addNickname( "elizabeth", "liz" )
    	fmt.Println("Outside method: ", people["elizabeth"].Nicknames )

    	addNickname( "elizabeth", "lizzy" )
    	fmt.Println("Outside method: ", people["elizabeth"].Nicknames )	
}

我期望的结果是 people["elizabeth"].Nicknames == [ "betsy", "liz", "lizzy" ],但是虽然 subject 被设置了,映射中的切片却没有被更新。

代码可以在 Go Playground 查看:https://play.golang.org/p/VejqTd0rltR

如果这是一个愚蠢的问题,我很抱歉,我找不到答案,而且我已经查找/实验了好几个小时!


更多关于Golang中向结构体映射的切片追加元素时值未设置的解决方案的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

addNickname 函数中,你从未直接向映射中的值进行追加,而是向它的一个副本(subject)进行追加。

如果你想对映射进行更改,要么必须在更改后更新映射中的值:https://play.golang.org/p/sCr0B2QRKEl 或者将你的映射更新为持有指向 Person 的指针,这样 subject 就能修改映射中的值:https://play.golang.org/p/8AZ2eLx0weh

更多关于Golang中向结构体映射的切片追加元素时值未设置的解决方案的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


问题在于你操作的是映射中结构体的副本,而不是映射中存储的原始结构体。在Go语言中,映射返回的是值的副本,修改副本不会影响映射中的原始值。

以下是修正后的代码:

package main

import (
	"fmt"
)

type Person struct {
	Userid    string
	Nicknames []string
}

var people map[string]Person

func addNickname(person string, nickname string) {
	// 获取结构体指针
	subject := &people[person]
	subject.Nicknames = append(subject.Nicknames, nickname)
	fmt.Println("In method - subject: ", subject.Nicknames)
	fmt.Println("In method - people: ", people[person].Nicknames)
}

func main() {
	elizabeth := Person{Userid: "emp01"}
	people = make(map[string]Person)
	people["elizabeth"] = elizabeth
	fmt.Println("People: ", people)

	addNickname("elizabeth", "betsy")
	fmt.Println("Outside method: ", people["elizabeth"].Nicknames)

	addNickname("elizabeth", "liz")
	fmt.Println("Outside method: ", people["elizabeth"].Nicknames)

	addNickname("elizabeth", "lizzy")
	fmt.Println("Outside method: ", people["elizabeth"].Nicknames)
}

或者,你也可以使用指针类型的映射来避免这个问题:

package main

import (
	"fmt"
)

type Person struct {
	Userid    string
	Nicknames []string
}

var people map[string]*Person

func addNickname(person string, nickname string) {
	subject := people[person]
	subject.Nicknames = append(subject.Nicknames, nickname)
	fmt.Println("In method - subject: ", subject.Nicknames)
	fmt.Println("In method - people: ", people[person].Nicknames)
}

func main() {
	elizabeth := &Person{Userid: "emp01"}
	people = make(map[string]*Person)
	people["elizabeth"] = elizabeth
	fmt.Println("People: ", people)

	addNickname("elizabeth", "betsy")
	fmt.Println("Outside method: ", people["elizabeth"].Nicknames)

	addNickname("elizabeth", "liz")
	fmt.Println("Outside method: ", people["elizabeth"].Nicknames)

	addNickname("elizabeth", "lizzy")
	fmt.Println("Outside method: ", people["elizabeth"].Nicknames)
}

两种方法都能正确更新映射中的切片,得到期望的结果:people["elizabeth"].Nicknames == [ "betsy", "liz", "lizzy" ]

回到顶部