从切片创建类型

huangapple go评论65阅读模式
英文:

Creating type from slices

问题

我想创建一个类似堆栈的数据类型。我想要在“顶部”添加和删除条目,并能够将其打印出来。在这个例子中,我想要创建一个用于遍历 XML 文档并跟踪当前路径的 XPath 类型。

所以我创建了一个类型 xPath []string,并编写了相应的函数,比如 push()、pop() 和 String()。

我的问题是,这个类型丢失了它的状态,这让我有点困惑,因为我以为切片是引用类型。而且,如果我尝试将我的函数改为指针接收器,我会遇到几个编译错误。为了解决这个问题,我只是将 []string 改为一个只有一个 []string 字段的结构体。尽管如此,我仍然觉得不能只用切片作为底层类型有点困扰。

请问正确的做法是什么?

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)

	// 输出: /
	// 期望输出: /rss/channel/items
}
英文:

I want to create a data type which acts like a stack. I want to add and remove entries at the "top", as well as being able to print it out. In this example an XPath type for traversing an xml document and keeping track of the current path.

So I created a type xPath []string, and write the appropriate functions, ie: push() pop() and String().

My problem here is that the type loses its state, which baffles me a bit since I thought slices were reference types. Also if I try changing my functions into pointer receivers I run into several compile errors. At this point just to get by the problem, I simply changed []string into a struct with a single []string field. Though it still bathers me that I can't make it work with just a slice as the underlying type.

What is the correct way to do this?

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: /
	// Wanted: /rss/channel/items
}

</details>


# 答案1
**得分**: 2

你的push函数没有做任何事情。

正确的push函数:
```go
func (xp *xPath) push(entry string) {
    *xp = append(*xp, entry)
}

在需要改变值(例如使用索引)的情况下,切片是引用类型。

另一方面,如果你想重新分配它们并替换整个切片,你应该使用指针。


关于栈,还有一些更好的方法:
可以参考这个问题

英文:

Your push function is doing nothing.

Correct push function:

func (xp *xPath) push(entry string) {
	*xp = append(*xp, entry)
}

Slices are reference types in cases where you want to change their values (e.g. using indexes).

On the other hand, if you want to reassign them and replace the whole slice, you should use pointers.


Also about the stack, the are some better approaches:
have a look at this question.

huangapple
  • 本文由 发表于 2023年2月17日 17:30:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/75482418.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定