Go语言中基于切片实现栈式XPath类型的正确方法
问题分析与解决
你的问题核心在于切片作为值接收者时,方法内的修改不会同步到原变量。虽然切片的底层数组是引用类型,但切片本身是一个包含指针、长度、容量的结构体,值接收者会完整拷贝这个结构体。append操作如果导致切片扩容,会生成新的底层数组,方法内的切片变量指向新数组,但原变量的切片结构体还是旧的,自然看不到修改。
正确实现:使用指针接收者
直接修改你的代码,把push方法的接收者改为指针类型即可:
package main import ( "fmt" "strings" ) type xPath []string // 使用指针接收者,确保修改作用于原切片 func (xp *xPath) push(entry string) { *xp = append(*xp, entry) } func (xp xPath) String() string { sb := strings.Builder{} sb.WriteString("/") sb.WriteString(strings.Join(xp, "/")) return sb.String() } func main() { xp := xPath{} xp.push("rss") xp.push("channel") xp.push("items") fmt.Println(xp) // Output: /rss/channel/items }
为什么指针接收者能解决问题?
当使用*xPath作为接收者时,方法内操作的是原切片结构体的引用:
*xp = append(*xp, entry)会直接修改原切片的指针、长度、容量字段- 无论
append是否触发扩容,原变量的切片都会同步更新状态
补充:pop方法的实现
如果需要实现pop,同样用指针接收者:
func (xp *xPath) pop() string { if len(*xp) == 0 { return "" } lastIdx := len(*xp) - 1 entry := (*xp)[lastIdx] *xp = (*xp)[:lastIdx] return entry }
内容的提问来源于stack exchange,提问作者Mikkel
相关产品推荐
相关产品推荐

