简单谈谈Golang中的字符串与字节数组

2020-01-28 13:55:17王振洲

从这个方法中我们其实能够看出 Go 语言处理标准字符串的逻辑:

1.标准字符串使用双引号表示开头和结尾;

2. 标准字符串中需要使用反斜杠 来 escape 双引号;

3. 标准字符串中不能出现换行符号 n ;

原始字符串解析的规则就非常简单了,它会将非反引号的所有字符都划分到当前字符串的范围中,所以我们可以使用它来支持复杂的多行字符串字面量,例如 JSON 等数据格式。


func (s *scanner) rawString() {
 s.startLit()

 for {
 r := s.getr()
 if r == '`' {
 break
 }
 if r < 0 {
 s.errh(s.line, s.col, "string not terminated")
 break
 }
 }

 s.nlsemi = true
 s.lit = string(s.stopLit())
 s.kind = StringLit
 s.tok = _Literal
}

无论是标准字符串还是原始字符串最终都会被标记成 StringLit 类型的 Token 并传递到编译的下一个阶段 —语法分析,在语法分析的阶段,与字符串相关的表达式都会使用如下的方法 BasicLit 对字符串进行处理:


func (p *noder) basicLit(lit *syntax.BasicLit) Val {
 switch s := lit.Value; lit.Kind {
 case syntax.StringLit:
 if len(s) > 0 && s[0] == '`' {
 s = strings.Replace(s, "r", "", -1)
 }
 u, _ := strconv.Unquote(s)
 return Val{U: u}
 }
}

无论是 import 语句中包的路径、结构体中的字段标签还是表达式中的字符串都会使用这个方法将原生字符串中最后的换行符删除并对字符串 Token 进行 Unquote,也就是去掉字符串两遍的引号等无关干扰,还原其本来的面目。

strconv.Unquote 方法处理了很多边界条件导致整个函数非常复杂,不仅包括各种不同引号的处理,还包括 UTF-8 等编码的相关问题,所以在这里也就不展开介绍了,感兴趣的读者可以在 Go 语言中找到 strconv.Unquote 方法详细了解它的执行过程。

介绍完了字符串的的解析过程,这一节就会继续介绍字符串的常见操作了,我们在这里要介绍的字符串常见操作包括字符串的拼接和类型转换,字符串相关功能的主要是通过 Go 语言运行时或者 strings 包完成的,我们会重点介绍运行时字符串的操作,想要了解 strings 包的读者可以阅读相关的代码,这里就不多介绍了。