『GoLang』string及其相关操作
- 1. 字符串简介
- 2. 字符串的拼接
- 3. 有关 string 的常用处理
- 3.1 strings 包
- 3.1.1 判断两个 utf-8 编码字符串是否相同
- 3.1.2 判断字符串 str 是否是以 prefix 开头
- 3.1.3 判断字符串 str 是否是以 suffix 结尾
- 3.1.4 判断 s 在 str 中首次出现的位置,如果没有出现返回 -1
- 3.1.5 判断 s 在 str 中最后一次出现的位置,如果没有出现返回 -1
- 3.1.6 查询非 ASCII 编码的字符在父字符串中的位置
- 3.1.7 字符串替换
- 3.1.8 返回 str 中 substr 出现的次数
- 3.1.9 重复 count 次的 str
- 3.1.10 转换大小写
- 3.1.11 去掉收尾空格符
- 3.1.12 去掉 str 两边的 cut 字符串
- 3.1.13 去掉 str 一边的cut字符串
- 3.1.14 以空格作为分隔符,将 str 分隔成切片
- 3.1.15 以 split 作为分隔符,将 str 分隔成切片
- 3.1.16 用 sep 把 slice 中的所有元素连接成字符串
- 3.1.17 判断字符串 s 是否包含子串 substr
- 3.1.18 判断字符串 s 是否包含 utf-8 码值 r
- 3.1.19 判断字符串 s 是否包含字符串 chars 中的任一字符
- 3.2 bytes 包
- 3.3 strconv 包
- 3.4 unicode 包
- 3.1 strings 包
1. 字符串简介
双引号:字符串使用双引号括起来,其中的相关的转义字符将被替换
str := "Hello World! \n Hello Gopher! \n"
输出:
Hello World!
Hello Gopher!
反引号:字符串使用反引号括起来,其中的相关的转义字符不会被替换
str := `Hello World! \n Hello Gopher! \n`
输出:
Hello World! \nHello Gopher! \n
双引号中的转义字符被替换,而反引号中原生字符串中的
\n
会被原样输出。
string
类型的零值是为长度为零的字符串,即空字符串 ""
Go 语言中的string
类型是一种值类型,存储的字符串是不可变的,如果要修改string
内容需要将string
转换为[]byte
或[]rune
,并且修改后的string
内容是重新分配的。
可以通过函数len()
来获取字符串所占的字节长度
str := "asd"
len(str)
如果需要获得字符,应该这么做:
package main
import "fmt"
func main() {
str := "我与春风皆过客,你携秋水揽星河。"
for _, char := range str {
fmt.Printf("%c", char)
}
}
输出:
我与春风皆过客,你携秋水揽星河。
获取字符串中某个字节的地址的行为是非法的,例如:
&str[i]
。
2. 字符串的拼接
直接使用运算符
str := "Beginning of the string " +
"second part of the string"
由于编译器行尾自动补全分号的缘故,加号
+
必须放在第一行。拼接的简写形式
+=
也可以用于字符串:s := "hel" + "lo, "
s += "world!"
fmt.Println(s) // 输出 “hello, world!”
里面的字符串都是不可变的,每次运算都会产生一个新的字符串,所以会产生很多临时的无用的字符串,不仅没有用,还会给 GC 带来额外的负担,所以性能比较差。
fmt.Sprintf()
str := fmt.Sprintf("%d:%s", 2018, "年")
fmt.Println(str) // 2018:年
内部使用
[]byte
实现,不像直接运算符这种会产生很多临时的字符串,但是内部的逻辑比较复杂,有很多额外的判断,还用到了interface
,所以性能一般。strings.Join()
str = strings.Join([]string{"hello", "world"}, ", ")
fmt.Println(str) // hello, world
Join
会先根据字符串数组的内容,计算出一个拼接之后的长度,然后申请对应大小的内存,一个一个字符串填入,在已有一个数组的情况下,这种效率会很高,但是本来没有,去构造这个数据的代价也不小。bytes.Buffer
var buffer bytes.Buffer
buffer.WriteString("hello")
buffer.WriteString(", ")
buffer.WriteString("world") fmt.Print(buffer.String()) // hello, world
这个比较理想,可以当成可变字符使用,对内存的增长也有优化,如果能预估字符串的长度,还可以用
buffer.Grow()
接口来设置capacity
strings.Builder
var b1 strings.Builder
b1.WriteString("ABC")
b1.WriteString("DEF") fmt.Print(b1.String()) // ABCDEF
strings.Builder
内部通过slice
来保存和管理内容。slice
内部则是通过一个指针指向实际保存内容的数组。strings.Builder
同样也提供了Grow()
来支持预定义容量。当我们可以预定义我们需要使用的容量时,strings.Builder
就能避免扩容而创建新的slice
了。strings.Builder
是非线程安全,性能上和bytes.Buffer
相差无几。
3. 有关 string 的常用处理
标准库中有四个包对字符串处理尤为重要:bytes
、strings
、strconv
和 unicode
包。
strings
包提供了许多如字符串的查询、替换、比较、截断、拆分和合并等功能bytes
包也提供了很多类似功能的函数,但是针对和字符串有着相同结构的[]byte
类型。因为字符串是只读的,因此逐步构建字符串会导致很多分配和复制。在这种情况下,使用bytes.Buffer
类型将会更有效strconv
包提供了布尔型、整型数、浮点数和对应字符串的相互转换,还提供了双引号转义相关的转换unicode
包提供了IsDigit
、IsLetter
、IsUpper
和IsLower
等类似功能,它们用于给字符分类
3.1 strings 包
3.1.1 判断两个 utf-8 编码字符串是否相同
func EqualFold(s, t string) bool
将
unicode
大写、小写、标题三种格式字符视为相同
func main() {
str1 := "Golang"
str2 := "golang"
fmt.Println(strings.EqualFold(str1, str2)) // true
}
3.1.2 判断字符串 str 是否是以 prefix 开头
strings.HasPrefix(s string,prefix string) bool
func main() {
str := "哈利·波特"
prefix := "哈利"
res := strings.HasPrefix(str, prefix)
fmt.Println(res) // true
}
3.1.3 判断字符串 str 是否是以 suffix 结尾
strings.HasSuffix(str string,suffix string) bool
func main() {
str := "哈利·波特"
prefix := "波特"
res := strings.HasSuffix(str, prefix)
fmt.Println(res) // true
}
3.1.4 判断 s 在 str 中首次出现的位置,如果没有出现返回 -1
strings.Index(str string,s string) int
func main() {
str := "哈利·波特"
s := "波特"
res := strings.Index(str, s)
fmt.Println(res) // 8,这是字节的index,不是Unicode字符数组的index
}
3.1.5 判断 s 在 str 中最后一次出现的位置,如果没有出现返回 -1
strings.LastIndex(str tring, s string) int
func main() {
str := "哈利·波特"
s := "·"
res := strings.LastIndex(str, s)
fmt.Println(res) // 6,这是字节的index,不是Unicode字符数组的index
}
3.1.6 查询非 ASCII 编码的字符在父字符串中的位置
func IndexRune(s string, r rune) int
func main() {
str := "哈利·波特"
s := '波'
res := strings.IndexRune(str, s)
fmt.Println(res) // 8,这是字节的index,不是Unicode字符数组的index
}
虽然搜索的时rune字符,但是返回的还是字节的索引。
3.1.7 字符串替换
strings.Replace(str string, old string, newStr string, n int) string
将
str
中的old
字符串替换为newStr
字符串,返回替换后的结果,n
参数为替换次数,n<0
表示无限次。
func main() {
str := "I love her, her name is red"
old := "her"
newStr := "him"
res := strings.Replace(str, old, newStr,1)
fmt.Println(res) // I love him, her name is red
res = strings.Replace(str, old, newStr,2)
fmt.Println(res) // I love him, him name is red
res = strings.Replace(str, old, newStr,-2)
fmt.Println(res) // I love him, him name is red
}
3.1.8 返回 str 中 substr 出现的次数
strings.Count(str string, substr string) int
func main() {
str := "I love her, her name is red"
substr := "e"
count := strings.Count(str, substr)
fmt.Println(count) // 5
}
3.1.9 重复 count 次的 str
strings.Repeat(str string, count int) string
func main() {
str := "love !"
count := 3
res := strings.Repeat(str, count)
fmt.Println(res) //love!love!love!
}
3.1.10 转换大小写
strings.ToLower(str string) string
strings.ToUpper(str string) string
func main() {
str := "I Love You !"
lower := strings.ToLower(str)
upper := strings.ToUpper(str)
fmt.Println(lower) // i love you !
fmt.Println(upper) // I LOVE YOU !
}
3.1.11 去掉收尾空格符
strings.TrimSpace(str string) string
func main() {
str := "I Love You ! "
res := strings.TrimSpace(str)
fmt.Println(res) // I Love You !
}
3.1.12 去掉 str 两边的 cut 字符串
strings.Trim(str string, cut string) string
func main() {
str := "ooI Love You !oo"
res := strings.Trim(str, "oo")
fmt.Println(res) // I Love You !
}
3.1.13 去掉 str 一边的cut字符串
strings.TrimLeft(str string, cut string) string
strings.TrimRight(str string, cut string) string
3.1.14 以空格作为分隔符,将 str 分隔成切片
strings.Fields(str string) []string
func main() {
str := "liu hai zhang"
res := strings.Fields(str)
fmt.Println(res)
for _, x := range res {
fmt.Println(x)
}
}
输出结果:
[liu hai zhang]
liu
hai
zhang
3.1.15 以 split 作为分隔符,将 str 分隔成切片
strings.Split(str string,split string) []string
func main() {
str := "liu-hai-zhuang"
res := strings.Split(str, "-")
fmt.Println(res) // [liu hai zhuang]
}
3.1.16 用 sep 把 slice 中的所有元素连接成字符串
strings.Join(slice []string,sep string) string
func main() {
slice := []string{"liu", "hai", "zhuang"}
res := strings.Join(slice, "-")
fmt.Println(res) // liu-hai-zhuang
}
3.1.17 判断字符串 s 是否包含子串 substr
func Contains(s, substr string) bool
func main() {
var str = "中国,台湾"
fmt.Println(strings.Contains(str, "台湾")) //true
fmt.Println(strings.Contains(str, "日本")) //false
}
3.1.18 判断字符串 s 是否包含 utf-8 码值 r
func ContainsRune(s string, r rune) bool
func main() {
var r rune = '中'
var str = "中国"
fmt.Println(strings.ContainsRune(str, r)) //true
fmt.Println(strings.ContainsRune(str, '日')) //false
}
3.1.19 判断字符串 s 是否包含字符串 chars 中的任一字符
func ContainsAny(s, chars string) bool
func main() {
var s = "我爱你,中国"
var chars = "我与春风皆过客"
var test = "日"
fmt.Println(strings.ContainsAny(s, chars)) //true
fmt.Println(strings.ContainsAny(s, test)) //false
}
3.2 bytes 包
方法类似strings包,不给过是针对[]byte
类型,这里省略,可以参考博客https://www.cnblogs.com/golove/p/3287729.html
3.3 strconv 包
3.3.1 string 转 int
func Atoi(s string) (i int, err error)
func main() {
numStr := "999"
num, err := strconv.Atoi(numStr)
if err != nil {
fmt.Println("can't convert to int")
} else {
fmt.Printf("type:%T value:%#v\n", num, num) // type:int value:999
}
}
另外还可以用
strconv
包下的:
func ParseInt(s string, base int, bitSize int) (i int64, err error)
或
func ParseUint(s string, base int, bitSize int) (n uint64, err error)
base
指定进制(2到36),如果base
为0
,则会从字符串前置判断,”0x”
是16
进制,”0”
是8
进制,否则是10
进制;
bitSize
指定结果必须能无溢出赋值的整数类型,0
、8
、16
、32
、64
分别代表int
、int8
、int16
、int32
、int64
;
3.3.2 int 转 string
func Itoa(i int) string
func main() {
num := 200
numStr := strconv.Itoa(num)
fmt.Printf("type:%T value:%#v\n", numStr, numStr) // type:string value:"200"
}
3.3.3 string 转 bool
func ParseBool(str string) (bool, error)
当
str
为:1
,t
,T
,TRUE
,true
,True
中的一种时为真值
当str
为:0
,f
,F
,FALSE
,false
,False
中的一种时为假值
func main() {
fmt.Println(strconv.ParseBool("t")) // true
fmt.Println(strconv.ParseBool("TRUE")) // true
fmt.Println(strconv.ParseBool("true")) // true
fmt.Println(strconv.ParseBool("True")) // true
fmt.Println(strconv.ParseBool("0")) //false
fmt.Println(strconv.ParseBool("f")) //false
}
3.3.4 string 转 float
func ParseFloat(s string, bitSize int) (f float64, err error)
bitSize
:32
或64
, 对应系统的位数
func main() {
strF := "250.56"
str, err := strconv.ParseFloat(strF, 64)
if err != nil {
fmt.Println(err)
}
fmt.Printf("type:%T value:%#v\n", str, str) // type:float64 value:250.56
}
3.3.5 float 转 string
func FormatFloat(f float64, fmt byte, prec, bitSize int) string
bitSize
表示f的来源类型(32
:float32
、64
:float64
),会据此进行舍入。
fmt
表示格式:'f'
(-ddd.dddd
)、'b'
(-ddddp±ddd
,指数为二进制)、'e'
(-d.dddde±dd
,十进制指数)、'E'
(-d.ddddE±dd
,十进制指数)、'g'
(指数很大时用'e'
格式,否则'f'
格式)、'G'
(指数很大时用'E'
格式,否则'f'
格式)。
prec
控制精度(排除指数部分):对'f'
、'e'
、'E'
,它表示小数点后的数字个数;对'g'
、'G'
,它控制总的数字个数。如果prec
为-1
,则代表使用最少数量的、但又必需的数字来表示f
。
func main() {
num := 250.56
str := strconv.FormatFloat(num, 'f', 4, 64)
fmt.Printf("type:%T value:%#v\n", str, str) // type:string value:"250.5600"
}
当然,以上类型转string的话,可以直接用fmt.Sprintf
实现。
3.4 unicode 包
3.4.1 判断字符大小写
func IsUpper(r rune) bool
func IsLower(r rune) bool
3.4.2 转换字符大小写
func ToUpper(r rune) rune
func ToLower(r rune) rune
3.4.3 判断字符 Title 格式
// 判断字符 r 是否为 Unicode 规定的 Title 字符
// 大部分字符的 Title 格式就是其大写格式
// 只有少数字符的 Title 格式是特殊字符
// 这里判断的就是特殊字符
func IsTitle(r rune) bool
3.4.4 字符转换 Title 格式
func ToTitle(r rune) rune
3.4.5 将字符转换为指定格式
func To(_case int, r rune) rune
_case
取值:UpperCase
、LowerCase
、TitleCase
3.4.6 判断字符是否是汉字
func main() {
for _, r := range "Hello 世界!" {
// 判断字符是否为汉字
if unicode.Is(unicode.Scripts["Han"], r) {
fmt.Printf("%c", r) // 世界
}
}
}
更多
unicode.Scripts
取值请参考:http://www.cnblogs.com/golove/p/3269099.html
3.4.7 字符判断
func IsDigit(r rune) bool
IsDigit
判断r
是否为一个十进制的数字字符func IsNumber(r rune) bool
IsNumber
判断r
是否为一个数字字符 (类别N
)func IsLetter(r rune) bool
IsLetter
判断r
是否为一个字母字符 (类别L
),汉字也是一个字母字符func IsSpace(r rune) bool
IsSpace
判断r
是否为一个空白字符,包括\t
,\n
,\v
,\f
,\r
func IsControl(r rune) bool
IsControl
判断r
是否为一个控制字符func IsGraphic(r rune) bool
IsGraphic
判断字符r
是否为一个“图形字符”,包括字母、标记、数字、标点、符号、空格func IsPrint(r rune) bool
IsPrint
判断字符r
是否为 Go 所定义的“可打印字符”,包括字母、标记、数字、标点、符号和 ASCII 空格func IsPunct(r rune) bool
IsPunct
判断r
是否为一个标点字符func IsSymbol(r rune) bool
IsSymbol
判断r
是否为一个符号字符
『GoLang』string及其相关操作的更多相关文章
- 『TensorFlow』梯度优化相关
tf.trainable_variables可以得到整个模型中所有trainable=True的Variable,也是自由处理梯度的基础 基础梯度操作方法: tf.gradients 用来计算导数.该 ...
- 『Golang』Martini框架入门
本文介绍golang中的优秀web开发框架martini! 序 Martini框架是使用Go语言作为开发语言的一个强力的快速构建模块化web应用与服务的开发框架.Martini是一个专门用来处理Web ...
- 『Golang』在Golang中使用json
由于要开发一个小型的web应用,而web应用大部分都会使用json作为数据传输的格式,所以有了这篇文章. 包引用 import ( "encoding/json" "gi ...
- 『GoLang』反射
方法和类型的反射 反射是应用程序检查其所拥有的结构,尤其是类型的一种能.每种语言的反射模型都不同,并且有些语言根本不支持反射.Go语言实现了反射,反射机制就是在运行时动态调用对象的方法和属性,即可从运 ...
- 『GoLang』数组与切片
数组 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列(这是一种同构的数据结构):这种类型可以是任意的原始类型例如整型.字符串或者自定义类型. 数组长度必须是一个常量表达式,并且必须是一个非负 ...
- 『GoLang』函数
函数介绍 Go语言函数基本组成包括: 关键字func 函数名 参数列表 返回值 函数体 返回语句 语法如下: func 函数名(参数列表) (返回值列表) { // 函数体 return } 除了ma ...
- 『GoLang』语法基础
标识符 字母或下划线开头 之后只能出现数字.字母.下划线 大小写敏感 Go语言关键字 break default func interface select case defer go map str ...
- 『Golang』MongoDB在Golang中的使用(mgo包)
有关在Golang中使用mho进行MongoDB操作的最简单的例子.
- 一:redis 的string类型 - 相关操作
*redisclient使用: =============一类:string的方法================ 介绍:string是redis的最简单类型,一个key相应一个value,strin ...
随机推荐
- deepin设置jdk全局变量
sudo vim /etc/bash.bashrc 在文件最后边添加 JAVA_HOME=jdk地址CLASSPATH=.:$JAVA_HOME/bin.tools.jarPATH=$JAVA_HOM ...
- 解决Mongoose 返回的文档过大导致模板引擎art-template无法渲染的问题,错误-RangeError: Maximum call stack size exceeded
参考:https://blog.csdn.net/qq_40659195/article/details/88411838 最近尝试用Node写一个小案例,使用到了MongoDB,使用过的人可以知道, ...
- 5、二进制安装K8s 之 部署kube-scheduler
二进制安装K8s之部署kube-scheduler 1.创建配置文件 cat > /data/k8s/config/kube-scheduler.conf << EOF KUBE_S ...
- 使用JS获取SessionStorage的值
参考:https://www.jb51.net/article/132729.htm 获取sessionStorage的意义 首先获取它是为了将获得的信息输出或者alert():让人容易看到, 其次, ...
- C++ CLI简介(什么是C++ CLI)
要知道C++/CLI是什么,首先知道什么是CLI. 一.CLI简介 CLI:(Common Language Infrastructure,通用语言框架)提供了一套可执行代码和它所运行需要的虚拟执行环 ...
- linux修改源镜像地址
1.1 CentOS修改yum源镜像地址为:mirrors.163.com (也可以改为阿里云镜像) 1.首先备份系统自带yum源配置文件/etc/yum.repos.d/CentOS-Base.re ...
- Gradient checking
所需文件:本地下载 Gradient Checking Welcome to the final assignment for this week! In this assignment you wi ...
- opencv入门系列教学(六)图像上的算术运算(加法、融合、按位运算)
0.序言 这一篇博客我们将学习图像的几种算术运算,例如加法,减法,按位运算等. 1.图像加法 我们可以通过OpenCV函数 cv.add() 或仅通过numpy操作 res=img1+img2 res ...
- 二.Go微服务--令牌桶
1. 令牌桶 1.1 原理 我们以 r/s 的速度向桶内放置令牌,桶的容量为 b , 如果桶满了令牌将会丢弃 当请求到达时,我们向桶内获取令牌,如果令牌足够,我们就通过转发请求 如果桶内的令牌数量不够 ...
- 眼见为实,看看MySQL中的隐藏列!
在介绍mysql的多版本并发控制mvcc的过程中,我们提到过mysql中存在一些隐藏列,例如行标识.事务ID.回滚指针等,不知道大家是否和我一样好奇过,要怎样才能实际地看到这些隐藏列的值呢? 本文我们 ...