go-extend: github.com/thinkeridea/go-extend/exstrings Index | Files

package exstrings

import "github.com/thinkeridea/go-extend/exstrings"

Package exstrings 收集常规的 string 操作,作为 go 标准库 strings 的扩展。 避免重复编写 string 相关操作代码,集中在一起更有利于优化代码,保证代码质量。

这个包会使用一些特殊的操作来减少内存开销,已获得更好的程序性能。

我也会在这个包重写 标准库 strings 里面的一些方法,以适用于不同场景的性能优化。

Index

Package Files

bytes.go convert.go doc.go join_int.go pad.go strings.go unsafe.go

Constants

const (
    // PadLeft 在左侧填充字符串为指定长度。
    PadLeft = iota

    // PadBoth 在两边填充字符串为指定长度,如果补充长度是奇数,右边的字符会更多一些。
    PadBoth

    // PadRight 在右侧填充字符串为指定长度。
    PadRight
)

func BothPad Uses

func BothPad(s, pad string, c int) string

BothPad 使用另一个字符串从两端填充字符串为指定长度, 如果补充长度是奇数,右边的字符会更多一些。

func Bytes Uses

func Bytes(s string) []byte

Bytes 把字符串转换成 []byte 类型,和 []byte(s) 操作结果一致,但是效率更高。

我进行了性能测试,它相比 []byte(s) 性能提升大约 14%,这仅仅是个实验的函数,它可能随着编译器优化而失去性能优势。 极端性能情况下依然可以使用它,它永远和 []byte(s) 的结果一致。

BenchmarkStandardLibraryStringToBytes-8         18584335                58.4 ns/op           192 B/op          1 allocs/op
BenchmarkExstringsStringToBytes-8               23752122                50.1 ns/op           192 B/op          1 allocs/op

func Copy Uses

func Copy(src string) string

Copy 拷贝一个字符串,在截取字符串之后,我们得到一个大字符串的引用,这会导致内存泄漏。 如果我们引用一个较大字符串的子串,建议进行 copy 以便 GC 可以快速回收大字符串。 例如: exstrings.Copy(s[10:50]) 这会得到一个子串的拷贝,原字符串不使用可以被 GC 回收。

func Join Uses

func Join(a []string, sep string) string

Join 使用 sep 连接 a 的字符串。 该方法是对标准库 strings.Join 修改,配合 unsafe 包能有效减少内存分配。

func JoinInt16s Uses

func JoinInt16s(i []int16, sep string) string

JoinInt16s 使用 sep 连接 []int16 并返回连接的字符串

func JoinInt32s Uses

func JoinInt32s(i []int32, sep string) string

JoinInt32s 使用 sep 连接 []int32 并返回连接的字符串

func JoinInt64s Uses

func JoinInt64s(i []int64, sep string) string

JoinInt64s 使用 sep 连接 []int64 并返回连接的字符串

func JoinInt8s Uses

func JoinInt8s(i []int8, sep string) string

JoinInt8s 使用 sep 连接 []int8 并返回连接的字符串

func JoinInts Uses

func JoinInts(i []int, sep string) string

JoinInts 使用 sep 连接 []int 并返回连接的字符串

func JoinToBytes Uses

func JoinToBytes(a []string, sep string) []byte

JoinToBytes 使用 sep 连接 a 的字符串并返回 []byte 该方法是对标准库 strings.Join 修改,配合 unsafe 包能有效减少内存分配。

func JoinUint16s Uses

func JoinUint16s(i []uint16, sep string) string

JoinUint16s 使用 sep 连接 []uint16 并返回连接的字符串

func JoinUint32s Uses

func JoinUint32s(i []uint32, sep string) string

JoinUint32s 使用 sep 连接 []uint32 并返回连接的字符串

func JoinUint64s Uses

func JoinUint64s(i []uint64, sep string) string

JoinUint64s 使用 sep 连接 []uint64 并返回连接的字符串

func JoinUint8s Uses

func JoinUint8s(i []uint8, sep string) string

JoinUint8s 使用 sep 连接 []uint8 并返回连接的字符串

func JoinUints Uses

func JoinUints(i []uint, sep string) string

JoinUints 使用 sep 连接 []uint 并返回连接的字符串

func LeftPad Uses

func LeftPad(s, pad string, c int) string

LeftPad 使用另一个字符串从左端填充字符串为指定长度。

func Pad Uses

func Pad(s, pad string, c, falg int) string

Pad 使用另一个字符串填充字符串为指定长度。

该函数返回 s 被从左端、右端或者同时两端被填充到制定长度后的结果。 填充方向由 falg 控制,可选值:PadLeft、PadBoth、PadRight。

在两边填充字符串为指定长度,如果补充长度是奇数,右边的字符会更多一些。

func Repeat Uses

func Repeat(s string, count int) string

Repeat 返回由字符串s的计数副本组成的新字符串。 该方法是对标准库 strings.Repeat 修改,对于创建大字符串能有效减少内存分配。

如果计数为负或 len(s) * count 溢出将触发panic。

func RepeatToBytes Uses

func RepeatToBytes(s string, count int) []byte

RepeatToBytes 返回由字符串s的计数副本组成的 []byte。 该方法是对标准库 strings.Repeat 修改,对于创建大字符串能有效减少内存分配。

如果计数为负或 len(s) * count 溢出将触发panic。

func Replace Uses

func Replace(s, old, new string, n int) string

Replace 替换字符串 该方法是对标准库 strings.Replace 修改,配合 unsafe 包能有效减少内存分配。

func ReplaceToBytes Uses

func ReplaceToBytes(s, old, new string, n int) []byte

ReplaceToBytes 替换字符串,并返回 []byte,减少类型转换 如果在字符串串中找不到子串,会发生内存拷贝 这个方法返回的 []byte 是安全,可以进行修改

func Reverse Uses

func Reverse(s string) string

Reverse 反转字符串,通过 https://golang.org/doc/code.html#Library 收集 使用 utf8.DecodeRuneInString 改进性能,请见:https://github.com/thinkeridea/go-extend/issues/5

func ReverseASCII Uses

func ReverseASCII(s string) string

ReverseASCII 反转字符串, 只支持单字节编码,可以提供更快的反转

func RightPad Uses

func RightPad(s, pad string, c int) string

RightPad 使用另一个字符串从右端填充字符串为指定长度。

func SubString Uses

func SubString(s string, start, length int) string

SubString 是 exutf8.RuneSubString 的别名,提供字符数量截取字符串的方法,针对多字节字符安全高效的截取 如果 start 是非负数,返回的字符串将从 string 的 start 位置开始,从 0 开始计算。例如,在字符串 “abcdef” 中,在位置 0 的字符是 “a”,位置 2 的字符串是 “c” 等等。 如果 start 是负数,返回的字符串将从 string 结尾处向前数第 start 个字符开始。 如果 string 的长度小于 start,将返回空字符串。

如果提供了正数的 length,返回的字符串将从 start 处开始最多包括 length 个字符(取决于 string 的长度)。 如果提供了负数的 length,那么 string 末尾处的 length 个字符将会被省略(若 start 是负数则从字符串尾部算起)。如果 start 不在这段文本中,那么将返回空字符串。 如果提供了值为 0 的 length,返回的子字符串将从 start 位置开始直到字符串结尾。

func UnsafeBothPad Uses

func UnsafeBothPad(s, pad string, c int) string

UnsafeBothPad 使用另一个字符串从两端填充字符串为指定长度, 如果补充长度是奇数,右边的字符会更多一些。

该函数使用 unsafe 包转换数据类型,降低内存分配。 Deprecated: 不在使用 Unsafe 前缀

func UnsafeJoin Uses

func UnsafeJoin(a []string, sep string) string

UnsafeJoin 使用 sep 连接 a 的字符串。 该方法是对标准库 strings.Join 修改,配合 unsafe 包能有效减少内存分配。

Deprecated: 不在使用 Unsafe 前缀,保持与标准库相同的命名

func UnsafeLeftPad Uses

func UnsafeLeftPad(s, pad string, c int) string

UnsafeLeftPad 使用另一个字符串从左端填充字符串为指定长度。

该函数使用 unsafe 包转换数据类型,降低内存分配。 Deprecated: 不在使用 Unsafe 前缀

func UnsafePad Uses

func UnsafePad(s, pad string, c, falg int) string

UnsafePad 使用另一个字符串填充字符串为指定长度。

该函数使用 unsafe 包转换数据类型,降低内存分配。

该函数返回 s 被从左端、右端或者同时两端被填充到制定长度后的结果。 填充方向由 falg 控制,可选值:PadLeft、PadBoth、PadRight。

在两边填充字符串为指定长度,如果补充长度是奇数,右边的字符会更多一些。

Deprecated: 不在使用 Unsafe 前缀

func UnsafeRepeat Uses

func UnsafeRepeat(s string, count int) string

UnsafeRepeat 返回由字符串s的计数副本组成的新字符串。 该方法是对标准库 strings.Repeat 修改,对于创建大字符串能有效减少内存分配。

如果计数为负或 len(s) * count 溢出将触发panic。

与标准库的性能差异(接近标准库性能的两倍):

BenchmarkUnsafeRepeat-8            	   50000	     28003 ns/op	  303104 B/op	       1 allocs/op
BenchmarkStandardLibraryRepeat-8   	   30000	     50619 ns/op	  606208 B/op	       2 allocs/op

Deprecated: 不在使用 Unsafe 前缀,保持与标准库相同的命名

func UnsafeReplace Uses

func UnsafeReplace(s, old, new string, n int) string

UnsafeReplace 替换字符串 该方法是对标准库 strings.Replace 修改,配合 unsafe 包能有效减少内存分配。

Deprecated: 不在使用 Unsafe 前缀,保持与标准库相同的命名

func UnsafeReplaceToBytes Uses

func UnsafeReplaceToBytes(s, old, new string, n int) []byte

UnsafeReplaceToBytes 替换字符串,并返回 []byte,减少类型转换 如果输入是字面量字符串,返回结果不可以修改

func UnsafeReverseASCII Uses

func UnsafeReverseASCII(s string) string

UnsafeReverseASCII 反转字符串, 只支持单字节编码,不支持字面量字符串, 原地反转字符串,可以提供更快的性能,但需要注意安全。

func UnsafeRightPad Uses

func UnsafeRightPad(s, pad string, c int) string

UnsafeRightPad 使用另一个字符串从右端填充字符串为指定长度。

该函数使用 unsafe 包转换数据类型,降低内存分配。 Deprecated: 不在使用 Unsafe 前缀

func UnsafeToBytes Uses

func UnsafeToBytes(s string) []byte

UnsafeToBytes 把 string 转换为 []byte 没有多余的内存开销。

这个函数可以提升 string 转 []byte 的性能,并极大的降低内存开销,但是却相当的危险,对于不明确这个函数的人来说不建议使用该函数。

这个函数是 exbytes.ToString 反向操作版,但是不像 exbytes.ToString 那么的稳定安全,该函数使用不当会导致程序直接崩溃,且无法恢复。

s := `{"k":"v"}`

b := exstrings.UnsafeToBytes(s)
// b[3] = 'k' // unexpected fault address 0x1118180
data := map[string]string{}
err := json.Unmarshal(b, &data)

fmt.Println(data, err)

这是一个使用的例子,如果我们需要转换一个字符串很方便,且开销非常的低。 但是一定要注意,b[3] = 'k' 如果尝试修改获得的 []byte 将直接导致程序崩溃,并且不可能通过 recover() 恢复。

实际上我们可以突破这个限制,这就要了解字符串的一些规则,下面的例子可以完美运行,并修改字符串:

s := strings.Repeat("A", 3)
b := exstrings.UnsafeToBytes(s)
b[1] = 'B'
b[2] = 'C'

fmt.Println(s, string(b))

非常完美,s和b变量的值都是 ABC, 为什么会这样呢?

这个就是 string 的内存分配方法, 字面量使用这种方式是没有办法修改的,因为这是在编译时就决定的,编译时会设定字符串的内存数据是只读数据。 如果程序运行时生成的数据,这种数据是可以安全使用该函数的,但是要当心你的字符串可能会被修改, 比如我们调用 json.Unmarshal(exstrings.UnsafeToBytes(s), &data), 如果 json 包里面出现修改输入参数,那么原来的字符串就可能不是你想想的那样。

使用该函数要明确两个事情:

- 确定字符串是否是字面量,或者内存被分配在只读空间上。
- 确保访问该函数结果的函数是否会按照你的意愿访问或修改数据。

我公开该函数经过很多思考,虽然它很危险,但是有时间却很有用,如果我们需要大批量转换字符串的大小写,而且不再需要原字符串,我们可以原地安全的修改字符串。 当然还有更多的使用方法,可以极大的提升我们程序的性能。

Package exstrings imports 8 packages (graph) and is imported by 1 packages. Updated 2019-11-04. Refresh now. Tools for package owners.