4week-4字符串库
一.字符串拼接
- 手里正好有字符串用 + Sprintf
- 手里有[]string切片用: string.Join
- 比如for循环频繁的多次拼接用:strings.builder
1.字符串拼接 + Sprintf
import (
"fmt"
fmt.Println(s3)
s4 := fmt.Sprint("xxxxxx", s1, s2)
fmt.Println(s4) //xxxxxxabc测试
}
- 结果:
2.字符串拼接 strings.Join
package main
import (
"fmt"
"strings"
)
func main() {
s1 := "abc"
s2 := "abc测试"
s5 := strings.Join([]string{s1, s2}, "-------")
fmt.Println(s5) //abc-------测试
}
- 结果:
3.strings.Builder构建器
import (
"fmt"
"strings"
)
func main() {
var builder strings.Builder //定义1个构建器.作用:生成字符串.
builder.Write([]byte(s1)) //s1是abc -号拼在abc后面
builder.WriteByte('-')
builder.WriteString(s2) //已经有的字符串
//上面拼好了字符串.
//下面演示使用
s6 := builder.String()
fmt.Println(s6)
}
- 结果
二.字符串查找
*效率
n表示元素个数,元素越多,查找耗时
-
string[index]查找某一个字节 O(1)
以下3种方法,不推荐使用,效率低,都是遍历,能用一次不要用2次
-
Index*方法,O(n)
-
Contains方法O(n)
-
Count方法O(n)
- Index:从左至右搜索,返回子串第一次出现的字节索引位置。未找到,返回-1。子串为空,也返回0。
- LastIndex:从右至左搜索,返回子串第一次出现的字节索引位置。未找到,返回-1。
- IndexByte、IndexRune与Index类似;LastIndexByte与LastIndex类似。
- IndexAny:从左至右搜索,找到给定的字符集字符串中任意一个字符就返回索引位置。未找到返回-1。
- Contains方法本质上就是Index方法,只不过返回bool值,方便使用bool值时使用。
- LastIndexAny与IndexAny搜索方向相反。
- Count:从左至右搜索子串,返回子串出现的次数。
1.Index
package main
import (
"fmt"
"strings"
)
func main() {
s := "www.baidu.com你好" //字符串里面是utf-8
for i, v := range s {
fmt.Println(i, v, string(v))
}
fmt.Println(strings.Index(s, "."))
fmt.Println(strings.Index(s, "w")) //从左到右找到第一个w返回其索引 ------>
fmt.Println(strings.Index(s, "你")) //你的索引是13
fmt.Println(strings.Index(s, "好")) //好的索引是16
fmt.Println(strings.Index(s, "t")) // -1表示没找到
// IndexByte 按照字节查找 strings.IndexByte(s, 0x62) () 里面必须是字节
fmt.Println(strings.IndexByte(s, 0x62)) //5 //0x62表示b, 返回4; b在索引4的位置
// IndexRune 按照字节查找,但是能找到更大的数.
fmt.Println(strings.IndexRune(s, 22909)) // 16
//IndexAny 查找字符串中是否包含 mo中的任意一个,先找到谁,就停止向后查找,并立刻返回其索引,
fmt.Println(strings.IndexAny(s, "mo")) //11
fmt.Println(strings.IndexAny(s, "你好")) //13 用utf8码查找
//LastIndex 精确从右向左查找coma这个单词,找到返回c的索引,否则返回-1 <------
fmt.Println(strings.LastIndex(s, "coma")) //-1
fmt.Println(strings.LastIndex(s, "w")) //2 <------
fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~")
}
2.Contains
s := "www.baidu.com你好"
//Contains 是否包含某字符串,返回bool
fmt.Println(strings.Count(s, "com"))
3.Count
s := "www.baidu.com你好"
fmt.Println(strings.Count(s, "w"))
fmt.Println(strings.Count(s, "ww"))
fmt.Println(strings.Count(s, "www"))
4.ToUpper ToLower 大小写转换
fmt.Println(strings.ToUpper(s))
fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~")
5.有没有指定的前缀
- 效率高:O(1) 定位效率高,只比较前后缀
s2 := "www.baidu.com你好"
fmt.Println(strings.HasPrefix(s2, "www"))
fmt.Println(strings.HasSuffix(s2, "com"))
三.字符串删除
## 1.TrimSpace
func main() {
s2 := " a b\tc\nd "
fmt.Println(strings.TrimSpace(s2)) //a b c
//d
2.TrimLeft 从前向后,不分顺序的删除," "后面的里字符,如果后面没有匹配上,就停止删除,
fmt.Println(strings.TrimLeft("abcdefg", "ab")) //cdefg
fmt.Println(strings.TrimLeft("abcdefg", "dabc")) //efg
fmt.Println(strings.TrimLeft("abcdefg", "bad")) //cdefg
3.TrimRight 从后向前,不分顺序的删除," "后面的里字符,如果后面没有匹配上,就停止删除
fmt.Println(strings.TrimRight("abcdefg", "aefg")) //abcd
fmt.Println(strings.TrimRight("abcdefg", "dfg")) //abcde
fmt.Println(strings.TrimRight("abcdefg", "efg")) //abcd
4.删除字符串中的www前缀
fmt.Println(strings.TrimPrefix("www.baidu.com你好", "www")) //.baidu.com你好
5.删除字符串中的com后缀
fmt.Println(strings.TrimSuffix("www.baidu.com", "com")) //www.baidu.
四.字符串分割
1.strings.Split以 " "里面的东西进行分割,返回切片
s := "www.baidu.com你好"
fmt.Printf("%T %[1]v\n", strings.Split(s, "com")) //返回字符串切片: []string [www.baidu. 你好]
fmt.Printf("%T %[1]v\n", strings.Split(s, ".")) //返回字符串切片: []string [www baidu com你好]
fmt.Printf("%T %[1]v\n", strings.Split(s, "t")) //返回字符串切片: []string [www.baidu.com你好]
fmt.Printf("%T %[1]v\n", strings.Split(s, "")) //空切,按照字符切 []string [w w w . b a i d u . c o m 你 好]
2.切几次 SplitN
fmt.Println(strings.SplitN(s, "com", -1)) //以 com为分隔符;小于0 能切多少下就切多少下 等于split []string [www.baidu. 你好]
fmt.Println(strings.SplitN(s, "com", 0)) // 等于0,不切,不用废物
fmt.Println(strings.SplitN(s, "com", 1)) //n切片至少1个元素//像strings.Split(s, "t")) //没切到返回字符串切片: []string [www.baidu.com你好]
fmt.Println(strings.SplitN(s, "com", 2)) //n切片至少2个元素[www.bai .com你好]
fmt.Println(strings.SplitN(s, "com", 3)) //n切片至少3个元素[www.bai . 你好]
fmt.Println(strings.SplitN(s, "com", 4)) //n切片至少4个元素[www.bai . 你好]
五.字符串替换
//replace 不能替换原有字符串,它会生成新的字符串
s := "www.baicom.com你好"
fmt.Println(strings.Replace(s, "com", "edu", 1)) //1替换1次 www.baiedu.com你好
fmt.Println(strings.Replace(s, "com", "edu", -1)) //-1=ReplaceAll 有多少,替换多少;www.baiedu.edu你好
fmt.Println(strings.ReplaceAll(s, "com", "edu")) //www.baiedu.edu你好
fmt.Println(strings.Replace(s, "com", "edu", 0)) //0 替换0次,返回s
s1 := strings.Replace(s, "com", "edu", 0) //返回1个新字符串,地址需要用header看
fmt.Println(s1)
六.Repeat,重复显示
fmt.Println(strings.Repeat("!@", 30))
}
七.Map字符串遍历
func main() {
s1 := "www.baidu.com你好"
fmt.Println(strings.Map(func(r rune) rune {
fmt.Println(r, "$$")
return r
}, s1))
}
map把字符串转为大写,
func main() {
s1 := "www.baidu.com你好"
fmt.Println(strings.Map(func(r rune) rune { 对字符串进行rune遍历.像for range
if r >= 'a' && r <= 'z' {
r = r - 0x20
}
return r
}, s1))
}
八.补码反码
package main
import "fmt"
func main() {
var i int8 = -1 //-1,的源码在内存中是0xff
fmt.Println(i)
var j uint8 = uint8(i) //把i是有符号整数,强制转为无符号整数,最高位是数字的一部分
//
//1. 正整数补码,反码,源码三码合一
//2. 负数,在计算机中用的是补码,给计算机看的
// -1的源码: 1000 0001 负数不用源码
// -1的反码: 1111 1110 符号位不变,其他位按位取反
// -1的补码: 1111 1111 符号位不变,其他位按位取反+1,给计算机看
// 还要给人看:补码的补码为源码 符号位不变,其他位按位取反+1
// 得到补码:0xff十六进制, 二进制0b11111111,在内存中需要赋予它类型,才有相应的意义
// if赋予0b11111111 uint8类型,那么0b11111111 强制转为无符号整数,最高位是数字的一部分 =255
// if赋予0b11111111,int8类型有符号 那么0b11111111 首位就是1 是负数,--> 再把0b1111 1111补码转为源码;0b1000 0001=-1给人看
fmt.Println(j)
}
九.类型转换
- 数值类型转换
- 低精度向高精度转换可以,高精度向低精度转换会损失精度
- 无符号向有符号转换,最高位是符号位
- 有符号向无符号转为最到位当数据用
- byte和int可以互相转换
- float和int可以相互转换,float到int会丢失精度
- bool和int不能相互转换
- 不同长度的int和float之间可以互相转换
- 但是,如果不使用无类型常量,有类型的计算如果类型不一致要报错,因为Go是对类型要求非常严苛的
- 语言,要强制类型转换。
1.
// untyped
// fmt.Println(int(3.14)) //不能转换 ,因为3.14是untyped
fmt.Println(float32(3.14)) //但是能用float32/64转
//如果想把3.14转为int.要先定义变量.用变量转
var a = 3.14 // float64
fmt.Println(int(a))
2.untyped rune和数字相加
b := 'a' //默认rune,当然可以和数字相加
c := b + 1
//为什么rune能和数组相加呢?
//因为untyped 做了隐式类型转换, 把int转为rune
fmt.Printf("c:%T %[1]v\n", c)
4.没有untyped rune相加
b := 'a' //类型是rune
c := 1 //类似默认是int,
d := b + c//为什么b+c不行呢,因为类型不同不能相加
fmt.Printf("d: %v\n", d)
//如果想相加,做强制类型转换
b := 'a' //类型是rune
c := 1 //类似默认是int,类型不同不能相加
d := b + rune(c) //把c转为rune.或者把b转为int
fmt.Printf("%T %[1]v\n", d)
5.byte和uint8相加.是同一个类型
var a byte = 'C' //a类型是byte也是uint8
var b uint8 = 49 //当然能和 uint8相加
fmt.Printf("%T %[2]T %[3]T %[1]v %[2]v %v ", a, b, a+b)
十.类型别名和类型定义
类型: type 名字 类型
别名:type 类型 = 别名
package main
import "fmt"
func main() {
type myByte byte // byte又定义了1个myByte类型
type byte = uint8 //go自带的别名, unint8和byte一模一样
var c myByte = 50
var a byte = 'C'
fmt.Printf("%T\n", c) //不能相加. myByte和byte不是一样类型
fmt.Printf("%T", a) //不能相加. myByte和byte不是一样类型
//如果要相加 强制类型转换
fmt.Println(byte(c) + a)
}
十一.字符串转换strconv
package main
import (
"fmt"
"strconv"
)
//以下操作都有通过第二个返回值判断,如果是nil转换成功
func main() {
// fmt.Println(string(127)) // ascii码表最后一个
// s1 := "127"
// fmt.Println(string(s1))
s1 := "127"
fmt.Println(strconv.Atoi(s1)) //ascii 转为 int 返回int和error nil是空表示没有错误
fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~")
// 10,表示按照10进制转,0表示int64类型
fmt.Println(strconv.ParseInt(s1, 10, 0)) //127 <nil>
// 这里要写0 ,4,8 ,16这类型数
fmt.Println(strconv.ParseInt(s1, 16, 64)) //295 <nil>
s2 := "3.141516"
//转为32位,返回float64 ,近似值,
fmt.Println(strconv.ParseFloat(s2, 32)) //3.1415159702301025 <nil>
//错误判断的2种写法
if t, err := fmt.Println(strconv.ParseFloat(s2, 32)); err != nil {
fmt.Println("error", err)
} else {
fmt.Println(t)
}
t1, err := fmt.Println(strconv.ParseBool("true"))
if err != nil { //如果错误不是空
panic(err) //终止程序运行
}
fmt.Println(t1)
}