Append string to string builder passed to a method and return updated string builder back?

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

Append string to string builder passed to a method and return updated string builder back?

问题

我正在从C#转向Golang,并尝试做一些在C#中有效的操作。我试图通过将字符串附加到resourceBuilder字符串构建器来填充它。

但是,我将resourceBuilder字符串构建器传递给AppendResource方法,并将字符串附加到传递给AppendResource方法的同一个字符串构建器,但当调用返回到Build方法时,我发现它没有附加到其中的所有内容。我确定我做错了什么,但我无法找出问题所在。

func Build(queryMap map[string][]QueryFilter, clientId int64, template []string) string {
    var resourceBuilder strings.Builder
    for _, propertyName := range template {
        queryFilters := queryMap[propertyName]
        AppendResource(queryFilters, resourceBuilder)
    }
    fmt.Println("output: ", resourceBuilder.String())
    return resourceBuilder.String()
}

func AppendResource(resourcesOpt []QueryFilter, resourceBuilder strings.Builder) {
    for _, qf := range resourcesOpt {
        if len(resourceBuilder.String()) == 0 {
            resourceBuilder.WriteString(qf.Resource.ResourceType)
            resourceBuilder.WriteString("-")
            resourceBuilder.WriteString(strconv.Itoa(qf.Resource.ResourceId))
        } else {
            resourceBuilder.WriteString("+")
            resourceBuilder.WriteString(qf.Resource.ResourceType)
            resourceBuilder.WriteString("-")
            resourceBuilder.WriteString(strconv.Itoa(qf.Resource.ResourceId))
        }
    }
}

如果我在C#中做同样的事情,那么resourceBuilder字符串构建器会在我的Build方法中正确更新。我是否做错了什么?

英文:

I am transitioning from C# to Golang and I am trying to do things what used to work in C#. I am trying to populate resourceBuilder string builder by appending string to it.

But I am passing resourceBuilder string builder to AppendResource method and appending strings to the same string builder passed to AppendResource method but when the call comes back to Build method, I don't see it has everything appended to it. I am sure something wrong I am doing but I cannot figure it out.

func Build(queryMap map[string][]QueryFilter, clientId int64, template []string) string {
	var resourceBuilder strings.Builder
	for _, propertyName := range template {
		queryFilters := queryMap[propertyName]
		AppendResource(queryFilters, resourceBuilder)
	}
    fmt.Println("output: ", resourceBuilder.String())
	return resourceBuilder.String()
}

func AppendResource(resourcesOpt []QueryFilter, resourceBuilder strings.Builder) {
	for _, qf := range resourcesOpt {
		if len(resourceBuilder.String()) == 0 {
			resourceBuilder.WriteString(qf.Resource.ResourceType)
			resourceBuilder.WriteString("-")
			resourceBuilder.WriteString(strconv.Itoa(qf.Resource.ResourceId))
		} else {
			resourceBuilder.WriteString("+")
			resourceBuilder.WriteString(qf.Resource.ResourceType)
			resourceBuilder.WriteString("-")
			resourceBuilder.WriteString(strconv.Itoa(qf.Resource.ResourceId))
		}
	}
}

If I do same thing in C# then resourceBuilder string builder gets updated properly in my Build method. Is there anything wrong I am doing.

答案1

得分: 1

问题在于你通过值传递了Builder,所以你创建了一个副本。方法对副本进行更改,所以调用方法看不到更改。

你可以通过传递指针(*strings.Builder)来修复它,但我不会将Builder传递给第二个方法。在我看来,这会导致更复杂且不太可重用的代码。除非这段代码在某个超高性能关键代码段中,轻微的性能提升不值得。

以下是我编写的代码:

func Build(queryMap map[string][]QueryFilter, clientId int64, template []string) string {
	var resourceBuilder strings.Builder
	for _, propertyName := range template {
		queryFilters := queryMap[propertyName]
		resourceBuilder.WriteString(GetResourceString(queryFilters))
	}
	fmt.Println("output: ", resourceBuilder.String())
	return resourceBuilder.String()
}


func GetResourceString(resourcesOpt []QueryFilter) string {
	var resourceBuilder strings.Builder
	for i, qf := range resourcesOpt {
		resourceBuilder.WriteString(qf.Resource.ResourceType)
		resourceBuilder.WriteString("-")
		resourceBuilder.WriteString(strconv.Itoa(qf.Resource.ResourceId))
		if i > 0 {
			resourceBuilder.WriteString("+")
		} 
	}
	return resourceBuilder.String()
}
英文:

The issue is that you are passing the Builder by value, so you are creating a copy of it. The method makes changes to the copy, so the calling method never sees the changes.

You could fix it by passing a pointer (*strings.Builder), but I wouldn't pass the Builder into the second method at all. In my mind, it makes for more complicated and less reusable code. Unless this code is in some ultra-performance critical section of code the slight performance boost wouldn't be worth it.

This is how I would code it:

func Build(queryMap map[string][]QueryFilter, clientId int64, template []string) string {
	var resourceBuilder strings.Builder
	for _, propertyName := range template {
		queryFilters := queryMap[propertyName]
		resourceBuilder.WriteString(GetResourceString(queryFilters))
	}
	fmt.Println("output: ", resourceBuilder.String())
	return resourceBuilder.String()
}


func GetResourceString(resourcesOpt []QueryFilter) string {
	var resourceBuilder strings.Builder
	for i, qf := range resourcesOpt {
		resourceBuilder.WriteString(qf.Resource.ResourceType)
		resourceBuilder.WriteString("-")
		resourceBuilder.WriteString(strconv.Itoa(qf.Resource.ResourceId))
		if i > 0 {
			resourceBuilder.WriteString("+")
		} 
	}
	return resourceBuilder.String()
}

huangapple
  • 本文由 发表于 2022年2月1日 01:59:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/70930662.html
匿名

发表评论

匿名网友

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

确定