Rust
Rust 的核心语言中只有一种字符串类型:str,字符串 slice,它通常以被借用的形式出现,&str。 字符串 slice:他们是一些储存在别处的 UTF-8 编码字符串数据的引用。
称作 String 的类型是由标准库提供的,而没有写进核心语言部分,它是可增长的、可变的、有所有权的、UTF-8 编码的字符串类型。当 Rust开发者 们谈到 Rust 的 “字符串”时,他们通常指的是 String 和字符串 slice &str类型,而不是其中一个。这一部分大部分是关于 String 的,不过这些类型在 Rust 标准库中都被广泛使用。String 和字符串 slice 都是 UTF-8 编码的。
赋值
在《Rust程序设计语言》中变量与数据的交互的方式(一):移动使用了如下实例,
fn main() {
println!("Hello,world!");
let s1 = String::from("hello");
let s2 = s1;
println!("{}",s2);
// println!("{}",s1);
// let s3 = s2.clone();
// println!("{}{}",s3,s2);
}
强调了Rust语言的特异点
1. Rust认为s1不再有效,故执行s2=s1之后尝试获取s1的值会报错
error[E0382]: use of moved value: `s1`
--> src/main.rs:6:19
|
4 | let s2 = s1;
| -- value moved here
5 | println!("{}",s2);
6 | println!("{}",s1);
| ^^ value used here after move
|
= note: move occurs because `s1` has type `std::string::String`,which does not implement the `Copy` trait
这个操作被称为“移动”,而不是浅拷贝。
而对于整型这样的在编译时已知大小的类型被整个存储在栈上,所以旧的整型变量在重新赋值后依然可用。
取子串
let s = String::from("kingeasternsun");
let firstname = &s[0..4];
let secondname = &s[4..];
println!("{}",firstname);
println!("{}",secondname);
使用..进行取子串的操作,需要注意的是由于String的移动特性,所以要在s前加&.
注意前面的警告,原因时我在代码里定义了一个Rectangle的结构体没有使用,Rust中如果定义了一个结构体但是没有使用会报警告,结构体后续会详细介绍。
使用 push 附加字符串
可以通过 push_str 方法来附加字符串 slice,从而使 String 变长:
let mut s = String::from("foo");
s.push_str("bar");
执行这两行代码之后 s 将会包含 “foobar”。push_str 方法获取字符串 slice,因为并不需要获取参数的所有权。例如,如果将 s2 的内容附加到 s1 中后自身不能被使用就糟糕了:
let mut s1 = String::from("foo");
let s2 = String::from("bar");
s1.push_str(&s2);
push 方法被定义为获取一个单独的字符作为参数,并附加到 String 中:
let mut s = String::from("lo");
s.push('l');
执行这些代码之后,s 将会包含 “lol”。
使用 + 运算符或 format! 宏级联字符串
通常我们希望将两个已知的字符串合并在一起。一种办法是像这样使用 + 运算符:
let s1 = String::from("Hello,");
let s2 = String::from("world!");
let s3 = s1 + &s2; // Note that s1 has been moved here and can no longer be used
执行完这些代码之后字符串 s3 将会包含 Hello,world!。
字符串遍历
如果你需要操作单独的 Unicode 标量值,最好的选择是使用 chars 方法。对 “नमस्ते” 调用 chars 方法会将其分开并返回六个 char 类型的值,接着就可以遍历结果来访问每一个元素了:
for c in "नमस्ते".chars() {
println!("{}",c);
}
न म स ् त े
bytes 方法返回每一个原始字节,这可能会适合你的使用场景:
for b in "नमस्ते".bytes() {
println!("{}",b);
}
这些代码会打印出组成 String 的 18 个字节,开头是这样的:
224
164
168
224
// ... etc
不过请记住有效的 Unicode 标量值可能会由不止一个字节组成。
更加详细的参见
字符串
golang
赋值
在golang中,string是一连串不可更改的byte的集合。对于文本字符串在golang中是把文本Unicode code points(runes)转为UTF-8编码格式的byte列表。
s := "hello,kingeastern"
fmt.Println(s[0]) //打印104 对应字符'h'的byte的数值
s[0] = '3'
由于一个非ASCII编码的字符转为UTF-8格式后占用两个或更多的byte,所以string的第i个byte并不一定是string的第i个字符。
取子串
s := "http://blog.csdn.net/wdy_yx"
fmt.Println(s[0]) //打印104 对应字符'h'的byte的数值
// s[0] = '3'
fmt.Println(s[:4])
fmt.Println(s[7:])
在golang中取子串的方式和大部分的编程语言一样使用:
,同时在golang中如果定义一个结构体但是没有使用是没问题的,但是import一个库但是没有使用是会报错的。
拼接
直接使用”+”就可以实现字符串的拼接
s := "http://blog.csdn.net/wdy_yx"
fmt.Println(s[0]) //打印104 对应字符'h'的byte的数值
// s[0] = '3'
fmt.Println(s[:4])
fmt.Println(s[7:])
fmt.Println("this is my websit:" + s)
前面讲过golang里面string类型里面的内容是不可变的,那为什么还可以执行拼接操作呢?
其实执行拼接操作后,原先的string并没有改变,而是拼接后的新字符串在另外一块内存中,s指向了这部分新的内存,可以看下面的样例:
s := "http://blog.csdn.net/wdy_yx"
t := s
s += "this is my websit:"
fmt.Println(t)
fmt.Println(s)
如果要进行多次拼接操作,更加高效的方式时使用bytes.Buffer。
代码如下:
var buffer bytes.Buffer //Buffer是一个实现了读写方法的可变大小的字节缓冲
for {
//获取要增加的字符
buffer.WriteString(piece)
}
在golang的string中,可以插入任意的byte通过十六进制或8进制方式。
16进制方式@H_347_404@\xhh,\x后面一定要跟两个数字h(0-9a-f)
8进制方式@H_347_404@\000,一定要有三个数字(0-7)
golang的字符串还有一种Raw string表示方式,用
``
而不是
""
包含字符。在Raw string中无需处理escape字符,引号里包含的字符是什么样的打印出来就是什么样子的,Raw string可以夸行。
s := `
http://blog.csdn.net/wdy_yx
this is my website
this return \n
`
fmt.Println(s)
Raw string的特性在处理正则表达式,HTML模板,JSON等非常方便。
UTF-8
在golang中所有字符都是utf-8编码的,某些字符可能占用多个byte,len函数返回的是byte个数,utf8.RuneCountInString返回的是rune个数。
所以len(s)返回12,utf8.RuneCountInString(s)返回8.
for range 遍历string时是按照rune为单位遍历的
所以@H_347_404@for i,r := range s遍历得到了汉字@H_347_404@世和@H_347_404@界。
fmt.Printf(“% x\n”,s) 按照byte进行打印
fmt.Printf(“% x\n”,[]rune(s)) 按照rune进行打印
s := "hello 世界"
fmt.Println(len(s))
fmt.Println(utf8.RuneCountInString(s))
for i,r := range s {
fmt.Printf("%d\t%q\t%x\n",i,r,r)
}
fmt.Println("****************")
for i,r := range []byte(s) {
fmt.Printf("%d\t%q\t%x\n",r)
}
fmt.Printf("% x\n",s)
fmt.Printf("%x\n",[]rune(s))
strings的其他强大函数
package main import ( "fmt" "strings" ) func main() { /* strings 包使用 */ str := "This is an example of a string" prefix := "This" if strings.HasPrefix(str,prefix) {//判断字符串prefix是否是字符串str的前缀 fmt.Printf("HasPrefix:the string '%s' have prefix %s\n",str,prefix) } suffix := "g" if strings.HasSuffix(str,suffix) {//判断字符串 suffix 是否是字符串str的后缀 fmt.Printf("HasSuffix:the string '%s' have suffix %s\n",suffix) } substr := "example" if strings.Contains(str,substr) {//判断字符串 str 是否包含字符串 substr fmt.Printf("Contains:the string '%s' contains '%s'\n",substr) } cStr :="中国" suffix = "国" if strings.HasSuffix(cStr,cStr,suffix) } substr="is" //Index返回字符串substr在字符串str中的第一个索引(-1表示字符串str不包含字符串substr),索引从0开始 pos := strings.Index(str,substr) fmt.Printf("Index:字符串 '%s' 在字符串 '%s' 中的位置是%d\n",substr,pos) //Index返回字符串substr在字符串str中最后出现位置的索引(-1表示字符串str不包含字符串substr),索引从0开始 lastPos := strings.LastIndex(str,substr) fmt.Printf("LastIndex:字符串 '%s' 在字符串 '%s' 中最后出现的位置是%d\n",lastPos) //indexRune返回unicode字符在字符串中第一次出现的位置 runePos := strings.IndexRune(str,'a') fmt.Printf("IndexRune:字符'a' 在字符串 '%s' 中出现的位置是%d\n",runePos) //IndexAny返回chars中的任意一个unicode字符在str中第一次出现的位置 //不好理解的话,就是从字符str的第一个字符开始找,如果当前字符在chars中存在,就返回当前字符的位置 //下面的测试例子中,"ai"中的i在第三个字符也就是2位置第一次出现了,先于a的出现 anyPos := strings.IndexAny(str,"ai") fmt.Printf("IndexAny:字符串'ai'的某个字符 在字符串 '%s' 中出现的位置是%d\n",anyPos) //Count返回字符串个数 count := strings.Count(str,"is") fmt.Printf("Count:the string 'is' has appeared %d times in '%s'\n",count,str) repeatStr := "repeat string!" repeatStr = strings.Repeat(repeatStr,2) fmt.Printf("Repeat:重复后的字符串为'%s'\n",repeatStr) upperStr := strings.ToUpper(str) fmt.Printf("ToUpper:字符串大写:'%s'\n",upperStr) lowerStr := strings.ToLower(upperStr) fmt.Printf("ToLower:字符串小写:'%s'\n",lowerStr) str = " \n\t 我是中国人 \n\t " newStr := strings.TrimSpace(str) fmt.Printf("原始字符串为:'%s'\n",str) fmt.Printf("TrimSpace:去掉两边的空格后字符串为:'%s'\n",newStr) cutset1 := "Ths" s1 := "ThisisGThiss" //Trim:的作用可以这么理解:从字符串s1的第一个字符开始,如果这个字符在cutset1中,那么就删除掉该字符,如果不存在就停止,然后 //从字符串s1的最后一个字符开始,如果这个字符在cutset1中,那么就删除掉该字符,如果不存在就停止 newStr1 := strings.Trim(s1,cutset1) fmt.Printf("Trim:'%s'去掉两边的'%s'后字符串为:'%s'\n",s1,cutset1,newStr1) //注意与strings.TrimPrefix的区别 //Trim:的作用可以这么理解:从字符串s1的第一个字符开始,如果这个字符在cutset1中,那么就删除掉该字符,如果不存在就停止 newStr2 := strings.TrimLeft(s1,cutset1) fmt.Printf("TrimLeft:'%s'去掉左边的'%s'后字符串为:'%s'\n",newStr2) //TrimPrefix去除前缀,如果cutset1如果s1的前缀,则s1保持不变 newStr4 := strings.TrimPrefix(s1,cutset1) fmt.Printf("TrimPrefix:去掉'%s'的前缀'%s'后的字符串为:'%s'\n",newStr4) cutset4:="This" newStr4 = strings.TrimPrefix(s1,cutset4) fmt.Printf("TrimPrefix:去掉'%s'的前缀'%s'后的字符串为:'%s'\n",cutset4,newStr4) //注意与strings.TrimSuffix的区别 newStr3 := strings.TrimRight(s1,cutset1) fmt.Printf("TrimRight:'%s'去掉右边的'%s'后字符串为:'%s'\n",newStr3) s5 := "ThisisGisThis" cutset5 := "This" newStr5 := strings.TrimSuffix(s5,cutset5) fmt.Printf("TrimSuffix:去掉'%s'的后缀'%s'后的字符串为:'%s'\n",s5,cutset5,newStr5) s6 := "to live or to die,it is a question \t,haha " //Fields把字符串以white space characters,as defined by unicode.IsSpace为分隔符进行分割 fmt.Printf("Fields are: %q\n",strings.Fields(s6)) //Split把字符串按照用户指定的字符作为分隔符分割 fmt.Printf("Split: are: %q\n",strings.Split(s6,",")) slice1 := strings.Split(s6,") //Join 把字符串slice用用户指定的字符串拼接起来 fmt.Printf("Split:The string is: %q\n",strings.Join(slice1,"#@")) fmt.Println("查找子串是否在指定的字符串中") fmt.Println(" Contains 函数的用法") fmt.Println("seafood contains foo",strings.Contains("seafood","foo")) //true fmt.Println("seafood contains bar","bar")) //false fmt.Println("seafood contains ''","")) //true fmt.Println(strings.Contains("","")) //true 这里要特别注意 fmt.Println("我是中国人 contain 中国",strings.Contains("我是中国人","中国")) //true //ContainsAny 判断字符串s中是否包含chars中的任意一个字符,也就是说chars中的任意一个字符出现在s中就返回true fmt.Println("") fmt.Println(" ContainsAny 函数的用法") fmt.Println("seafood contains bar",strings.ContainsAny("seafood","bar")) //false fmt.Println(strings.ContainsAny("","")) // false fmt.Println("") fmt.Println(" ContainsRune 函数的用法") fmt.Println(strings.ContainsRune("我是中国",'我')) // true 注意第二个参数,用的是字符 fmt.Println("") fmt.Println(" Count 函数的用法") fmt.Println(strings.Count("cheese","e")) // 3 fmt.Println(strings.Count("five","")) // before & after each rune result: 5,源码中有实现 fmt.Println(strings.Count("fivesss","")) // before & after each rune result: 8,源码中有实现 fmt.Println("") fmt.Println(" EqualFold 函数的用法") fmt.Println(strings.EqualFold("Go","go")) //大小写忽略 fmt.Println("FieldsFunc") //相当于用函数做为参数,支持匿名函数,让字符串按照用户自定义的规则进行分割, // 匿名函数中,参数ch rune表示字符串的某个字符,如果返回true,表示该字符作为分隔符,返回false,则保留 for _,record := range []string{" aaa*1892*122","aaa\taa\t","124|939|22"} { fmt.Println(strings.FieldsFunc(record,func(ch rune) bool { switch { case ch > '5': return true } return false })) } fmt.Println("") fmt.Println(" Map 函数的用法") 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 } //map用来按照用户指定的规则对字符串中每个字符进行处理变为新的字符 fmt.Println(strings.Map(rot13,"'Twas brillig and the slithy gopher...")) fmt.Println("") fmt.Println(" Repeat 函数的用法") fmt.Println("ba" + strings.Repeat("na",2)) //banana fmt.Println("") fmt.Println(" Replace 函数的用法") fmt.Println(strings.Replace("oink oink oink","k","ky",2)) fmt.Println(strings.Replace("oink oink oink","oink","moo",-1)) fmt.Println("") fmt.Println(" Split 函数的用法") fmt.Printf("%q\n",strings.Split("a,b,c",")) fmt.Printf("%q\n",strings.Split("a man a plan a canal panama","a ")) fmt.Printf("%q\n",strings.Split(" xyz ","")) fmt.Printf("%q\n",strings.Split("","Bernardo O'Higgins")) fmt.Println("") fmt.Println(" SplitAfter 函数的用法") //SplitAfter 和Split的区别在于SplitAfter包含了分隔符 fmt.Printf("%q\n",strings.SplitAfter("/home/m_ta/src","/")) //["/" "home/" "m_ta/" "src"] fmt.Println("") fmt.Println(" SplitAfterN 函数的用法") fmt.Printf("%q\n",strings.SplitAfterN("/home/m_ta/src","/",2)) //["/" "home/m_ta/src"] fmt.Printf("%q\n",strings.SplitAfterN("#home#m_ta#src","#",-1)) //["#" "home#" "m_ta#" "src"] fmt.Println("") fmt.Println(" SplitN 函数的用法") fmt.Printf("%q\n",strings.SplitN("/home/m_ta/src",1)) fmt.Printf("%q\n",2)) //["" "home/m_ta/src"] fmt.Printf("%q\n",-1)) //["" "home" "m_ta" "src"] fmt.Printf("%q\n",strings.SplitN("home,m_ta,src",",2)) //["home" "m_ta,src"] fmt.Printf("%q\n",strings.SplitN("#home#m_ta#src",-1)) //["/" "home/" "m_ta/" "src"] }
原文链接:https://www.f2er.com/go/187535.html