3

我正在尝试更改 Go 中的现有字符串,但我不断收到此错误“无法分配给 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"))
}

这是我的代码,我希望将小写更改为大写,但我无法更改字符串。为什么?我怎样才能改变它?

PS 我希望只使用 fmt 包!

提前致谢。

4

3 回答 3

7

你不能......它们是不可变的。来自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

于 2014-11-05T22:14:10.190 回答
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
于 2014-11-06T00:02:09.193 回答
3

在 Go 中,字符串是不可变的。这是做你想做的事情的一种非常糟糕的方式(操场

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

于 2014-11-05T22:19:02.907 回答