How can I assign a new char into a string in Go?

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

How can I assign a new char into a string in Go?

问题

我正在尝试修改Go中的一个现有字符串,但我一直收到这个错误信息:"cannot assign to new_str[i]"

package main
import "fmt"

func ToUpper(str string) string {
    new_str := str
    for i:=0; i<len(str); i++{
        if str[i]>='a' && str[i]<='z'{
            chr:=uint8(rune(str[i])-'a'+'A')
            new_str[i]=chr
        }
    }
    return new_str
}

func main() {
    fmt.Println(ToUpper("cdsrgGDH7865fxgh"))
}

这是我的代码,我希望将小写字母改为大写字母,但我无法修改字符串。为什么?我该如何修改它?

附言:我希望仅使用fmt包!

提前感谢。

英文:

I'm trying to alter an existing string in Go but I keep getting this error "cannot assign to new_str[i]"

package main
import &quot;fmt&quot;

func ToUpper(str string) string {
    new_str := str
    for i:=0; i&lt;len(str); i++{
    	if str[i]&gt;=&#39;a&#39; &amp;&amp; str[i]&lt;=&#39;z&#39;{
            chr:=uint8(rune(str[i])-&#39;a&#39;+&#39;A&#39;)
            new_str[i]=chr
   		}
    }
    return new_str
}

func main() {
    fmt.Println(ToUpper(&quot;cdsrgGDH7865fxgh&quot;))
}

This is my code, I wish to change lowercase to uppercase but I cant alter the string. Why? How can I alter it?

P.S I wish to use ONLY the fmt package!

Thanks in advance.

答案1

得分: 8

你不能改变字符串的内容,因为它们是不可变的。根据Golang语言规范

字符串是不可变的:一旦创建,就无法更改字符串的内容。

但是,你可以将其转换为[]byte切片并进行修改:

func ToUpper(str string) string {
    new_str := []byte(str)
    for i := 0; i < len(str); i++ {
        if str[i] >= 'a' && str[i] <= 'z' {
            chr := uint8(rune(str[i]) - 'a' + 'A')
            new_str[i] = chr
        }
    }
    return string(new_str)
}

工作示例:http://play.golang.org/p/uZ_Gui7cYl

英文:

You can't... they are immutable. From the Golang Language Specification:

> Strings are immutable: once created, it is impossible to change the contents of a string.

You can however, cast it to a []byte slice and alter that:

func ToUpper(str string) string {
    new_str := []byte(str)
	for i := 0; i &lt; len(str); i++ {
		if str[i] &gt;= &#39;a&#39; &amp;&amp; str[i] &lt;= &#39;z&#39; {
			chr := uint8(rune(str[i]) - &#39;a&#39; + &#39;A&#39;)
			new_str[i] = chr
		}
	}
	return string(new_str)
}

Working sample: http://play.golang.org/p/uZ_Gui7cYl

答案2

得分: 4

使用range并避免不必要的转换和分配。字符串是不可变的。例如,

package main

import "fmt"

func ToUpper(s string) string {
    var b []byte
    for i, c := range s {
        if c >= 'a' && c <= 'z' {
            if b == nil {
                b = []byte(s)
            }
            b[i] = byte('A' + rune(c) - 'a')
        }
    }
    if b == nil {
        return s
    }
    return string(b)
}

func main() {
    fmt.Println(ToUpper("cdsrgGDH7865fxgh"))
}

输出:

CDSRGGDH7865FXGH
英文:

Use range and avoid unnecessary conversions and allocations. Strings are immutable. For example,

package main

import &quot;fmt&quot;

func ToUpper(s string) string {
	var b []byte
	for i, c := range s {
		if c &gt;= &#39;a&#39; &amp;&amp; c &lt;= &#39;z&#39; {
			if b == nil {
				b = []byte(s)
			}
			b[i] = byte(&#39;A&#39; + rune(c) - &#39;a&#39;)
		}
	}
	if b == nil {
		return s
	}
	return string(b)
}

func main() {
	fmt.Println(ToUpper(&quot;cdsrgGDH7865fxgh&quot;))
}

Output:

<pre>
CDSRGGDH7865FXGH
</pre>

答案3

得分: 3

在Go语言中,字符串是不可变的。以下是一种非常糟糕的实现方式(playground):

package main

import "fmt"

func ToUpper(str string) string {
    new_str := ""
    for i := 0; i < len(str); i++ {
        chr := str[i]
        if chr >= 'a' && chr <= 'z' {
            chr = chr - 'a' + 'A'
        }
        new_str += string(chr)
    }
    return new_str
}

func main() {
    fmt.Println(ToUpper("cdsrgGDH7865fxgh"))
}

这种方式存在以下问题:

  • 将字符串视为字符,如果是UTF-8编码会有问题,应该使用range str来处理
  • 字符串拼接速度慢,会有很多内存分配,可以考虑使用bytes.Buffer
  • 已经有一个非常好的库函数可以实现这个功能,即strings.ToUpper

值得注意的是,对于代码中的new_str += string(chr)这一行,字符串是不可变的,所以这实际上是创建了一个以chr结尾的新字符串,而不是扩展原来的字符串。对于较长的字符串来说,这种方式非常低效,因为分配的内存量会随字符串长度的平方增长。

下次可以直接使用strings.ToUpper函数!

英文:

In Go strings are immutable. Here is one very bad way of doing what you want (playground)

package main

import &quot;fmt&quot;

func ToUpper(str string) string {
	new_str := &quot;&quot;
	for i := 0; i &lt; len(str); i++ {
		chr := str[i]
		if chr &gt;= &#39;a&#39; &amp;&amp; chr &lt;= &#39;z&#39; {
			chr = chr - &#39;a&#39; + &#39;A&#39;
		}
		new_str += string(chr)
	}
	return new_str
}

func main() {
	fmt.Println(ToUpper(&quot;cdsrgGDH7865fxgh&quot;))
}

This is bad because

  • you are treating your string as characters - what if it is UTF-8? Using range str is the way to go
  • appending to strings is slow - lots of allocations - a bytes.Buffer would be a good idea
  • there is a very good library routine to do this already strings.ToUpper

It is worth exploring the line new_str += string(chr) a bit more. Strings are immutable, so what this does is make a new string with the chr on the end, it doesn't extend the old string. This is wildly inefficient for long strings as the allocated memory will tend to the square of the string length.

Next time just use strings.ToUpper!

huangapple
  • 本文由 发表于 2014年11月6日 05:14:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/26767255.html
匿名

发表评论

匿名网友

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

确定