//string的结构
// runtime/strings.go:
// 字符串是不可变, 值类型, 指针字段指向底层一个字节数组
type stringStruct struct{
str unsafe.Pointer
len int
}
// str是值类型, 默认零值是"", 而非nil
func main() {
var s string
fmt.Printf("%#v
", s)
fmt.Println("" == s)
}
//""
//true
//字符串不可变: (要想改变, 先转为[]byte类型,修改后在转为str)
func main() {
s := "a毛"
s[0] = 10
}
//.main.go:7:7: cannot assign to s[0]
//字符串不可变: 指针指向底层一个字符数组: 不能取元素的地址(不存在底层字节数组首地址==str地址的说法)
func main() {
s := "abc"
fmt.Println(&s)
fmt.Println(&s[0])
}
//.main.go:7:14: cannot take the address of s[0]
// 字符串有len属性, 无cap属性
func main() {
var s string
fmt.Println(len(s),cap(s))
}
//.main.go:7:24: invalid argument s (type string) for cap
//字符串: len获取占用多少字节
func main() {
s := "m"
s2 := "毛"
fmt.Println(len(s))
fmt.Println(len(s2))
}
//1
//3
小结: unicode编码, 字符占1个字节,汉字占3个字节.(go采用默认utf8编码)
//指针指向底层一个字节数组(可以通过下标取元素),即从字符串下标取出元素的类型都是 byte类型
func main() {
s := "a毛"
fmt.Printf("%T, %v
", s[0], s[0])
fmt.Printf("%T, %c
", s[1], s[1])
fmt.Println([]byte(s))
}
//uint8, 97
//uint8, æ
//[97 230 175 155]
//字符类型
//定义字符: 默认都是int32类型,即手动定义的都是rune类型
func main() {
s := 'a'
s2 := '我'
fmt.Printf("%T,%v
", s, s)
fmt.Printf("%T,%v
", s2, s2)
}
//int32,97
//int32,25105
//别名
type byte = uint8 //1个字节,对应ascii
type rune = int32 //4个字节,rune类型(别名) 专门用来存储unicode码点
//别名不会改变实际类型
//别名属于同一类型,可以相互赋值
func main() {
type int2 = int
var a int2
fmt.Printf("%T
", a)
var b int
b = a
fmt.Println(b)
}
//int
//0
// 字符串切片
func main() {
s := "abc"
fmt.Println([]byte(s))
fmt.Println(s[1:2])
}
//[97 98 99]
//b
func main() {
s := "abc"
fmt.Println([]byte(s))
fmt.Println(s[1:])
}
//[97 98 99]
//bc
func main() {
s := "abc"
fmt.Println([]byte(s))
fmt.Println(s[:2])
}
//[97 98 99]
//ab
//截取出的字符串可能是乱码
func main() {
s := "abc毛台"
fmt.Println([]byte(s))
fmt.Println(s[3:])
fmt.Println(s[3:4])
}
//[97 98 99 230 175 155 229 143 176]
//毛台
//�
// 遍历字符串: for: byte方式(会有乱码)
func main() {
s := "毛台abc"
for i := 0; i < len(s); i++ {
fmt.Printf("%c", s[i]) //会有乱码,因为是按字节来遍历的
}
}
//æ¯ å °abc
//遍历字符串:for range
func main() {
s := "毛台abc"
for _, v := range s {
fmt.Printf("%c", v) //会自动识别unicode拼接成对应汉字
}
}
//毛台abc
//定义多行字符串: `` 里面的控制字符不会被转义
func main() {
s := `hello
world`
fmt.Println(s)
}
//hello
//
world
//格式化输出
func main() {
s := "a"
fmt.Println(s[0]) //97: 默认是10进制输出
fmt.Printf("%d
", s[0]) //97: 十进制
fmt.Printf("%x
", s[0]) //61: 十六进制
fmt.Printf("%o
", s[0]) //141: 八进制(小写o)
fmt.Printf("%O
", s[0]) //0o141: 八进制(大写o)
}
//fmt的帮助文档可看到
%s //字符串格式
%x //十六进制
%d //十进制数字格式
%c //字符格式
%p //地址
//字符串转为字符数组
func main() {
s := "abc毛台"
bytes := []byte(s)
fmt.Printf("%T,%v", bytes, bytes)
}
//[]uint8,[97 98 99 230 175 155 229 143 176]
// byte rune string之间的转换
func main() {
r:= '我'
s:=string(r) //rune to string
b:=byte(r) //rune to byte
s2:=string(b) //byte to string
r2:=rune(b) //byte to rune
fmt.Println(s,b,s2,r2)
}
// 连接字符串
s = "ab"+
"cd"
s == "abcd"
//字符串append函数
func main() {
s := "abc毛台"
var bs []byte
bs = append(bs, s...)
fmt.Println(bs)
}
//[97 98 99 230 175 155 229 143 176]
//slice的append函数
func main() {
arr := []int{1, 2, 3}
arr2 := []int{4, 5, 6}
arr = append(arr, arr2...)//展开运算
fmt.Println(arr)
}
//[1 2 3 4 5 6]
//性能: join bytes获取字符串
func test()string{
var s string
for i:=0;i<1000;i++ {
s+= "a"
}
return s
}
func test()string{
s:=make([]string,1000) // 分配足够的内存,避免中途扩张底层数组
for i:=0;i<1000;i++ {
s[i] = "a"
}
return strings.Join(s, "")
}
- utf8包
//检测字符串存储的字节数组的合法性
func main() {
s := "abc毛台"
fmt.Println([]byte(s))
fmt.Println(s[3:4])
fmt.Println(utf8.ValidString(s[3:4]))
}
//[97 98 99 230 175 155 229 143 176]
//�
//false
//utf8包: 检测字符串真实长度
func main() {
s := "abc毛台"
println(utf8.RuneCountInString(s))
}
//5
方法 |
介绍 |
len("我s") |
结果是4, 求长度 |
utf8.RuneCountInString("我s") |
结果是2, 求长度 |
+或fmt.Sprintf |
拼接字符串 |
strings.Split |
分割 |
strings.contains |
判断是否包含 |
strings.HasPrefix,strings.HasSuffix |
前缀/后缀判断 |
strings.Index(),strings.LastIndex() |
子串出现的位置 |
strings.Join(a[]string, sep string) |
join操作 |