golang中当我们在使用 strings.Title, Upper, Lower, Fold函数是都会提提已启用,建议我们使用能够正确处理Unicode的字符处理扩展包golang.org/x/text/cases 来代替内置strings包中的相关函数,用于处理字符大小写(如 Title, Upper, Lower, Fold)
text/cases 大小写处理定义
golang官方提供的这个扩展包text/cases 主要通过 Caser这个对象来处理字符串的大小写,他的定义如下:
type Caser
func Fold(opts ...Option) Caser
func Lower(t language.Tag, opts ...Option) Caser
func Title(t language.Tag, opts ...Option) Caser
func Upper(t language.Tag, opts ...Option) Caser
func (c Caser) Bytes(b []byte) []byte
func (c Caser) Reset()
func (c Caser) Span(src []byte, atEOF bool) (n int, err error)
func (c Caser) String(s string) string
func (c Caser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error)
type Option
func HandleFinalSigma(enable bool) Option
Caser Example测试用例
import (
"fmt"
"testing"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
func ExampleTextCases() {
src := []string{
"hello world!",
"你好golang!",
"i with dot",
"'n ijsberg",
"here comes O'Brian",
}
for _, c := range []cases.Caser{
cases.Upper(language.SimplifiedChinese), // 指定语言为简体中文
cases.Lower(language.Und),
// cases.Lower(language.Tag{}), // 注意这里的Tag{}和Und是一样的效果
cases.Title(language.Und, cases.NoLower), // 可选参数使用
} {
fmt.Println("")
for _, s := range src {
// 获取当前运行的函数名
ff := fmt.Sprintf("%#v", c)
fname, _ := strings.CutPrefix(strings.Split(ff, ")(")[0], "cases.Caser{t:(*cases.")
fmt.Printf("cases函数:%v 输入字符串: %s 转换后: %s \n", fname, s, c.String(s))
}
}
//output:
// cases函数:undUpperCaser 输入字符串: hello world! 转换后: HELLO WORLD!
// cases函数:undUpperCaser 输入字符串: 你好golang! 转换后: 你好GOLANG!
// cases函数:undUpperCaser 输入字符串: i with dot 转换后: I WITH DOT
// cases函数:undUpperCaser 输入字符串: 'n ijsberg 转换后: 'N IJSBERG
// cases函数:undUpperCaser 输入字符串: here comes O'Brian 转换后: HERE COMES O'BRIAN
// cases函数:undLowerCaser 输入字符串: hello world! 转换后: hello world!
// cases函数:undLowerCaser 输入字符串: 你好golang! 转换后: 你好golang!
// cases函数:undLowerCaser 输入字符串: i with dot 转换后: i with dot
// cases函数:undLowerCaser 输入字符串: 'n ijsberg 转换后: 'n ijsberg
// cases函数:undLowerCaser 输入字符串: here comes O'Brian 转换后: here comes o'brian
// cases函数:titleCaser 输入字符串: hello world! 转换后: Hello World!
// cases函数:titleCaser 输入字符串: 你好golang! 转换后: 你好Golang!
// cases函数:titleCaser 输入字符串: i with dot 转换后: I With Dot
// cases函数:titleCaser 输入字符串: 'n ijsberg 转换后: 'N Ijsberg
// cases函数:titleCaser 输入字符串: here comes O'Brian 转换后: Here Comes O'Brian
}
Caser结构体定义参考
可见这个结构体的属性t 是一个接口SpanningTransformer, 而这个接口又继承了Transformer接口
type Caser struct {
t transform.SpanningTransformer
}
type SpanningTransformer interface {
Transformer
Span(src []byte, atEOF bool) (n int, err error)
}
// Transformer transforms bytes.
type Transformer interface {
Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error)
Reset()
}
Option定义参考
这里外部可用的Option选项 通过暴露NoLower, Compact 这2个变量和1个函数 HandleFinalSigma(enable bool) 来提供给外部使用 , 如: cases.Title(language.Und, cases.HandleFinalSigma(true)).String("xxx")
// An Option is used to modify the behavior of a Caser.
type Option func(o options) options
var (
// NoLower disables the lowercasing of non-leading letters for a title
// caser.
NoLower Option = noLower
// Compact omits mappings in case folding for characters that would grow the
// input. (Unimplemented.)
Compact Option = compact
)
type options struct {
noLower bool
simple bool
// TODO: segmenter, max ignorable, alternative versions, etc.
ignoreFinalSigma bool
}
func getOpts(o ...Option) (res options) {
for _, f := range o {
res = f(res)
}
return
}
func noLower(o options) options {
o.noLower = true
return o
}
func compact(o options) options {
o.simple = true
return o
}
// HandleFinalSigma specifies whether the special handling of Greek final sigma
// should be enabled. Unicode prescribes handling the Greek final sigma for all
// locales, but standards like IDNA and PRECIS override this default.
func HandleFinalSigma(enable bool) Option {
if enable {
return handleFinalSigma
}
return ignoreFinalSigma
}
细心的你可能已经注意到这里的这个Option可选参数函数在这里他是通过在内部定义了2个常量来提供给包外使用,这个我们之前的其他库中的Option用法zap logger 日志记录库 options接口类型 可选参数(函数)使用 总结-CSDN博客稍有不同,但是原理都是一样的。