gostring用法java_Go语言 字符串(string)

什么是字符串

一个Go语言字符串是一个任意字节的常量序列。

Go语言字符串与其他语言(Java,C++,Python)字符串的不同点

Go语言中字符串的字节使用UTF-8编码表示Unicode文本,因此Go语言字符串是变宽字符序列,每一个字符都用一个或者多个字符表示,这跟其他的(C++,Java,Python 3)的字符串类型有着本质上的不同,后者为定宽字符序列。

其他语言的字符串中的单个字符可以被字节索引,而Go语言中只有在字符串只包含7位的ASCII字符(因为它们都是用一个单一的UTF-8字节表示)时才可以被字节索引。那么这是不是表示Go语言在字符串处理能力上就比其他语言弱呢?答案时否定的,应为Go语言支持一个字符一个字符的迭代,而且标准库中存在大量的字符串操作函数,最后我们还可以将Go语言的字符串转化为Unicode码点切片(类型为 [ ]rune),切片是支持直接索引的。

对于英文文本,Go使用8位来表示每一个字节,而Java或Python则需要16位或更多。采用UTF-8编码,使得Go语言无需关系机器码的排列顺序,也无需编码解码来使用其他语言。

注:每一个Unicode字符都有一个唯一的叫做“码点”的标识数字。在Go语言中,一个单一的码点在内存中以 rune 的形式表示,rune表示int32类型的别名

字面量,操作符和转义

在Go语言中,字符串字面量使用双引号 "" 或者反引号 ' 来创建。双引号用来创建可解析的字符串,支持转义,但不能用来引用多行;反引号用来创建原生的字符串字面量,可能由多行组成,但不支持转义,并且可以包含除了反引号外其他所有字符。双引号创建可解析的字符串应用最广泛,反引号用来创建原生的字符串则多用于书写多行消息,HTML以及正则表达式。

比如下面的这些例子,输出结果完全一致

text1 := "\"Hello GoLang\",I said"

text2 :=`"Hello GoLang",I said` //这个在Java中就无法编译成功

虽然Go语言中的字符串是不可变的,但是字符串支持 + 级联操作和+=追加操作,比如下面这个例子

text1 := "Hello" + " GoLang"

text1 += " Java"

fmt.Println(text1) // 输出 Hello GoLang Java

如果底层的字符串容量不够大,不能适应添加的字符串,级联追加操作将导致底层的字符串被替换。

下面是有关字符串的一些操作符描述

text1 := "abcdefg"

fmt.Println(text1[n]) //获取字符串索引位置为n的原始字节,比如a为97

fmt.Println(text1[n:m]) //截取得字符串索引位置为 n 到 m-1 的字符串

fmt.Println(text1[n:]) //截取得字符串索引位置为 n 到 len(s)-1 的字符串

fmt.Println(text1[:m]) //截取得字符串索引位置为 0 到 m-1 的字符串

fmt.Println(len(text1)) //获取字符串的字节数

fmt.Println(utf8.RuneCountInString(text1)) //获取字符串字符的个数

fmt.Println([]rune(text1)) // 将字符串的每一个字节转换为码点值,比如这里会输出[97 98 99 100 101 102 103]

fmt.Println(string(text1[n])) // 获取字符串索引位置为n的字符值

比较字符串

Go语言中的字符串是支持常规的比较操作(,==,!=,<=,>=),这些操作符会在内存中一个字节一个字节的比较,但是在执行比较操作时,常会出现以下三种问题:

①有些 Unicode 编码的字符可以用两个或者多个不同的字节序列来表示。

如果我们只关心ASCII字符,这个问题将不会存在,若是非ASCII字符,那么我们可以通过自定义标准化函数来隔离接受这些字符串。

②用户希望将不同的字符看作是相同的。

比如字符二,2,Ⅱ,②都可以看作相同的意思,那么用户输入2时,就得匹配这些相同意思的其他字符。这个也可以通过自定义标准化函数来解决。

③字符的排序跟语言的类型有关。

字符与字符串

在Go语言中,可以用rune或者int32来表示一个字符。

字符可以通过+=操作符在一个循环中往字符串末尾追加字符,但这并不是最有效的方式,我们可以使用类似Java中的StringBuilder 来实现。

var buffer bytes.Buffer //创建一个空的 bytes.Buffer

for {

if piece,ok = getNextValidString();ok {

buffer.WriteString(piece) //通过 WriteString 方法将我们需要串联的字符串写入到 buffer 中

}else {

break

}

}

fmt.Println(buffer.String()) //最后用于取回整个级联的字符串

使用 bytes.Buffer 进行字符串的累加比起+=要高效的多,尤其是在面对大数量的字符串时。

将字符串一个字符一个字符的迭代出来,可以通过 for range 循环

text1 := "abcdefg"

for index,char := range text1 {

fmt.Printf("%d %U %c \n",index,char,char)

}

字符串索引与切片

在所有的7位ASCII字符中,通过索引提取其字符是可以的,比如下面的例子

func main() {

text1 := "abcdefg"

fmt.Println(string(text1[0])) //获取索引为0的字符(核心就是通过字节来转为字符,这里字节只能为一个)

}

但是对于任意字符串来讲,上面并不一定可靠,因为有些字符可能有多个字节。为了解决这个问题,我们就需要使用字符串切片,这样返回的将是一个字符而不是一个字节。

text1 := "abcdefg"

chars := []rune(text1) //先把字符串转为rune切片

for _,char := range chars {

fmt.Println(string(char))

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值