golang中字符串是一种基本类型(string),是一个不可改变的UTF-8字符序列:
字符串创建后,就不可改变;即不允许修改。
golang支持两种类型的字符串字面量:
\n\r
等)会被替换掉;字符串声明与初始化非常容易:
var s1 string
s2 := "hello"
多行字符串使用反引号:
s := `hello
world!
line2`
fmt.Println(s)
len()返回字符串中的字节数(非字符数目),索引操作s[i]返回字符串s中第i个字节的值(非Ascii码返回对应字节的数值)。要获取对应字符数(包含非ASCII字符时)需要使用utf8.RuneCountInString
s1 := "W字符"
fmt.Println(len(s1)) // 7 (一个汉字3个字节)
fmt.Println(utf8.RuneCountInString(s1)) // 3
字符串比较的方式有如下三种:
==
:直接比较,区分大小写(效率最高);strings.Compare(a,b)
:返回值为 int, 0 表示两数相等,1 表示 a>b, -1 表示 a
strings.EqualFold(a,b)
:直接返回是否相等,不区分大小写。golang中有多种字符串拼接方法:
+
):最常用、方便的,但每次拼接都会生成一个新的字符串,效率较低;一般简单拼接直接使用+,字符串数组/切片拼接为字符串时用Join,多条不相关字符串拼接时用Builder。
var buff bytes.Buffer
buff.WriteString("hello")
buff.WriteRune('字')
buff.WriteString("符")
fmt.Println(buff.String()) // hello字符
var build strings.Builder
build.WriteString("hello")
build.WriteRune('字')
build.WriteString("符")
fmt.Println(build.String()) // hello字符
go中可通过切片方式快速获取子串s=src[low:high]
(指定索引范围,‘左含右不含’)。索引不能越界,否则会导致panic异常。
s1 := "abcdef"
fmt.Println(s1[1:4],s1[1:],s1[:1]) // bcd bcdef a
对于包含中文的字符串,需要转换为rune后操作(否则会出现乱码):
name := "test中文字符串测试"
runeName := []rune(name)
log.Printf("ori-len: %v, rune-len: %v", len(name), len(runeName))
for i := 2; i <= len(runeName); i++ {
log.Printf("%v-len: %v", i, string(runeName[:i]))
}
有两种遍历方式:下标与range。下标方式遍历时,输出的是每个字节;要输出对应的Unicode字符,需要通过range方式。
s1 := "W字符"
// 输出7个数值(每个字节对应数值)
for i:=0; i<len(s1); i++{
fmt.Println(s1[i])
}
// 输出三个字符(分别:W 字 符)
for i, v:=range s1{
fmt.Println(i, string(v))
}
golang中字符串内容默认不能修改,若要修改需要转换为[]byte或[]rune类型修改后再转回:
s1 := "W字符"
b1 := []byte(s1)
fmt.Println(len(b1)) // 7
b1[0] = 'M'
fmt.Println(string(b1)) // M字符
r1 := []rune(s1)
fmt.Println(len(r1)) // 3
r1[1] = '世'
fmt.Println(string(r1)) //W世符
strings中包含了一些常用的字符串操作函数,在涉及到字符串修改时,返回新的串。
func Map(mapping func(rune) rune, s string) string
,根据mapping函数修改s中的字符,并返回修改后新的串;若mapping返回负值,则删除对应字符。
rot13 := func(r rune) rune {
switch {
case r >= 'A' && r <= 'Z':
return 'A' + (r-'A'+13)%26
case r >= 'a' && r <= 'z':
return 'a' + (r-'a'+13)%26
}
return r
}
fmt.Println(strings.Map(rot13, "Twas brillig and the slithy gopher..."))
用于读取字符串,实现了io.Reader、io.ReaderAt、io.Seeker、io.WriterTo、io.ByteScanner、io.RuneScanner。
r := strings.NewReader("abcdefghijklmn")
fmt.Println("total len:", r.Len()) // 14
var buf []byte
buf = make([]byte, 5)
readLen, err := r.Read(buf)
fmt.Println("read len:", readLen) // 5
if err != nil {
fmt.Println("error:", err)
}
fmt.Println(string(buf)) // abcde
fmt.Println("remain len:", r.Len()) // 9 读取到了5个 剩余未读是14-5
fmt.Println("size:", r.Size()) // 14 字符串的长度
用于字符串替换;placer中包含要替换字符串的列表,且是线程安全的:
r := strings.NewReplacer("<", "<", ">", ">")
fmt.Println(r.Replace("This is HTML!")) // This is <b>HTML</b>!
strconv包用于字符串与其它类型间的转换:
FormatInt(i, 10)
);ParseInt(s, 10, 0)
);1,t,T,TRUE,true,True
为真;0,f,F,FALSE,false,False
为假);在转换时,会出现两种类型的错误:
func ParseInt(s string, base int, bitSize int)(i int64, err error)
常用的Atoi,是一个简易版,相当于ParseInt(s, 10, 0)
。
func FormatFloat(f float64, fmt byte, prec, bitSize int) string
FormatFloat参数只接收64位浮点,要转换32位浮点可:
var v32 float32 = 3.1415926535
var v64 float64 = 3.1415926535
s32 := fmt.Sprintf("%.4f", v32)
s32_1 := strconv.FormatFloat(float64(v32), 'f', 4, 32)
s64 := strconv.FormatFloat(v64, 'f', 4, 64)
格式标记:
f := 100.123456789
fmt.Println(strconv.FormatFloat(f, 'b', 5, 32)) // 13123382p-17
fmt.Println(strconv.FormatFloat(f, 'e', 5, 32)) // 1.00123e+02
fmt.Println(strconv.FormatFloat(f, 'E', 5, 32)) // 1.00123E+02
fmt.Println(strconv.FormatFloat(f, 'f', 5, 32)) // 100.12346
fmt.Println(strconv.FormatFloat(f, 'g', 5, 32)) // 100.12
fmt.Println(strconv.FormatFloat(f, 'G', 5, 32)) // 100.12
通过ParseFloat(s string, bitSize int) (float64, error)
可方便地把字符串转为float64;若要转换为float32,需要bitSize传32,并把结果直接转换为float32即可。
v := "3.1415926535"
r64, _ := strconv.ParseFloat(v, 64)
r, _ := strconv.ParseFloat(v, 32)
r32 := float32(r)
fmt.Println(r64, r32)