www.zhblog.net

strconv、strings 包


Go 的字符串基本上是个[]byte,在程序语言强弱类型的光谱中,Go 位于强类型的一端,对于字符串与其他类型之间的转换,往往得自行处理,在这方面,strconv就提供了不少的函数。

例如,最常用的是将字符串解析为某个类型:

func ParseBool(str string) (bool, error)
func ParseFloat(s string, bitSize int) (float64, error)
func ParseInt(s string, base int, bitSize int) (i int64, err error)
func ParseUint(s string, base int, bitSize int) (uint64, error)

若是解析失败,返回的错误会是*NumError

type NumError struct {
    Func string // 来源函数(ParseBool、ParseInt、ParseUint、ParseFloat)
    Num  string // 输入字符串
    Err  error  // 失败的源由(ErrRange、ErrSyntax 等)
}

如果要将其他类型附加至字符串,可以使用 Append 名称开头的函数:

func AppendBool(dst []byte, b bool) []byte
func AppendFloat(dst []byte, f float64, fmt byte, prec, bitSize int) []byte
func AppendInt(dst []byte, i int64, base int) []byte
func AppendQuote(dst []byte, s string) []byte
func AppendQuoteRune(dst []byte, r rune) []byte
func AppendQuoteRuneToASCII(dst []byte, r rune) []byte
func AppendQuoteRuneToGraphic(dst []byte, r rune) []byte
func AppendQuoteToASCII(dst []byte, s string) []byte
func AppendQuoteToGraphic(dst []byte, s string) []byte
func AppendUint(dst []byte, i uint64, base int) []byte

以上的附加函数设计上接收[]byte,Go 字符串本质上是个[]byte,调用这些函数时只要明确类型转换就可以了,例如:

b := []byte("bool:")
b = strconv.AppendBool(b, true)
fmt.Println(string(b))

对于大量的字符串附加处理,可以使用stringsBuilder,一来操作上比较方便,二来可看看是否可获取较好的性能表现:

type Builder
    func (b *Builder) Cap() int
    func (b *Builder) Grow(n int)
    func (b *Builder) Len() int
    func (b *Builder) Reset()
    func (b *Builder) String() string
    func (b *Builder) Write(p []byte) (int, error)
    func (b *Builder) WriteByte(c byte) error
    func (b *Builder) WriteRune(r rune) (int, error)
    func (b *Builder) WriteString(s string) (int, error)

例如,来个简单的评测:

package mypackage

import (
    "testing"
    "strings"
)

func plusAppend() string {
    c := ""
    for i := 0; i < 100000; i++ {
        c += "test"
    }
    return c
}

func buliderAppend() string {
    var b strings.Builder
    for i := 0; i < 100000; i++ {
        b.WriteString("test")
    }
    return b.String()
}

func BenchmarkPlusAppend(b *testing.B) {
    for i := 0; i < b.N; i++ {
        plusAppend()
    }
}

func BenchmarkBuilderAppend(b *testing.B) {
    for i := 0; i < b.N; i++ {
        buliderAppend()
    }
}

看一下性能上是否有差异:

C:\workspace\go-exercise>go test -bench="." mypackage
goos: windows
goarch: amd64
pkg: mypackage
BenchmarkPlusAppend-4                  1        4162865000 ns/op
BenchmarkBuilderAppend-4            1946            655490 ns/op
PASS
ok      mypackage       6.614s

如果想将字符串当成是个io.Reader来源,可以使用strings.Reader

type Reader
    func NewReader(s string) *Reader
    func (r *Reader) Len() int
    func (r *Reader) Read(b []byte) (n int, err error)
    func (r *Reader) ReadAt(b []byte, off int64) (n int, err error)
    func (r *Reader) ReadByte() (byte, error)
    func (r *Reader) ReadRune() (ch rune, size int, err error)
    func (r *Reader) Reset(s string)
    func (r *Reader) Seek(offset int64, whence int) (int64, error)
    func (r *Reader) Size() int64
    func (r *Reader) UnreadByte() error
    func (r *Reader) UnreadRune() error
    func (r *Reader) WriteTo(w io.Writer) (n int64, err error)

strings还有个Replacer,用于一对一的字符串取代:

type Replacer
    func NewReplacer(oldnew ...string) *Replacer
    func (r *Replacer) Replace(s string) string
    func (r *Replacer) WriteString(w io.Writer, s string) (n int, err error)

什么是一对一的取代呢?看看官方文件中提到的范例就知道了:

package main

import (
    "fmt"
    "strings"
)

func main() {
    r := strings.NewReplacer("<", "<", ">", ">")
    fmt.Println(r.Replace("This is <b>HTML</b>!"))
}

其他对于字符串的比较、分割、大小写转换等处理,strings中提供了一系列的函数,strings的文件中都有代码示范。


展开阅读全文

评论

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 心情