『GoLang』string及其相关操作
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 mainimport "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 redres = strings.Replace(str, old, newStr,2)fmt.Println(res) // I love him, him name is redres = 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 := 3res := 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, "台湾")) //truefmt.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)) //truefmt.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)) //truefmt.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 := 200numStr := 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")) // truefmt.Println(strconv.ParseBool("TRUE")) // truefmt.Println(strconv.ParseBool("true")) // truefmt.Println(strconv.ParseBool("True")) // truefmt.Println(strconv.ParseBool("0")) //falsefmt.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.56str := 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及其相关操作相关推荐
- 『Golang』Martini框架入门
本文介绍golang中的优秀web开发框架martini! 序 Martini框架是使用Go语言作为开发语言的一个强力的快速构建模块化web应用与服务的开发框架.Martini是一个专门用来处理Web ...
- 一:redis 的string类型 - 相关操作
*redisclient使用: =============一类:string的方法================介绍:string是redis的最简单类型,一个key相应一个value,string ...
- Lua string字符串相关操作
前言 字符串操作是 区分大小写的 一.字符串赋值 "" or '' 双引号或单引号 都表字符串 string1 = "a" string2 = 'b' prin ...
- 『GoLang』协程与通道
作为一门 21 世纪的语言,Go 原生支持应用之间的通信(网络,客户端和服务端,分布式计算)和程序的并发.程序可以在不同的处理器和计算机上同时执行不同的代码段.Go 语言为构建并发程序的基本代码块是 ...
- 『C++』string类模拟实现
深拷贝与浅拷贝 首先来看一段代码 #include <iostream> #include <string.h> #include <assert.h>class ...
- python 动漫卡通人物图片大全,『TensorFlow』DCGAN生成动漫人物头像_下
一.计算图效果以及实际代码实现 计算图效果 实际模型实现 相关介绍移步我的github项目. 二.生成器与判别器设计 生成器 相关参量, 噪声向量z维度:100 标签向量y维度:10(如果有的话) 生 ...
- 算法中的『前缀和』及『差分』思想详解
一.基本原理以及实现 1. 一维前缀和 一维前缀和的定义:对于一个从下标从『1』开始的长度为『nnn』的一维数组 『a1,a2,a3,...,ana_1,a_2,a_3,...,a_na1,a2, ...
- Java String类的相关操作
Java String类的相关操作 一.如何遍历字符串 //法一 String str="hello world"; for(int i=0;i<str.length();i ...
- Python 标准库之 shutil 高阶文件操作『详细』
Python标准库之 shutil 高阶文件操作『详细』 文章目录 Python标准库之 shutil 高阶文件操作『详细』 一.Python shutil介绍
最新文章
- #HTTP协议学习# (七)代理
- Latex 数学符号表
- Paxos第三篇 - Paxos成员组变更
- java定义json数组_Java面试题:json该如何定义?json与xml的区别有哪些?
- [转载] python中异常处理的四个句子_Python学习笔记总结(四)异常处理
- rk3399_secureboot在linux环境中操作说明
- 广州uc优视java面试_UC优视(UC浏览器)面试经验
- 关于Movie Studio插入素材格式问题
- java 任意 符号_哪种符号表示表面可用任意方法获得?()
- net share列出了Windows的默认共享(包括C盘)
- npm ERR! could not determine executable to run
- 荣耀畅玩7c能用鸿蒙吗,荣耀畅玩7C评测:人脸识别双摄 超高性价比
- 用友U9 BP不执行
- mysql日期函数之DATEDIFF() if()用法 case when用法
- 深度linux时间.年日调整,deepin深度商店中的Linux版应用体验分享(一)
- 纯JAVA实现雷电飞机大战<可本地联机>
- 前端项目 - 博客系统(纯页面)
- 如何在局域网内进行内部访问网站?
- 自然语言处理——词性标注、词干提取、词形还原
- platform设备驱动简介
热门文章
- 王道——数据结构——图(1)
- ChatGPT 的情感智能:机器人是否能够感受到情绪?
- 禅道-软件测试缺陷管理工具
- 安卓开发中,release安装包安装后,打开app后再按home键,再次点击程序图标app再次重新启动的解决办法
- 终于给小学生铁粉说清AI教杨超越姐姐跳舞的秘决了
- 移动“5G资费”曝光,看完价格,网友直呼:这次太良心了!
- 多目标蚂蚁狮子优化算法(Matlab代码实现)
- linux学习——硬盘分区和格式化篇
- java毕业设计动漫网站Mybatis+系统+数据库+调试部署
- css td文字不换行,html td nowrap不换行属性使用方法