string
操做在編程中具備極高的頻率,那麼string
中有哪些有用的方法呢?golang
按照字典序比較兩個字符串,一般狀況下直接使用=
,>
,<
會更快一些。編程
字符串s
中是否包含substr
,返回true或者false。bash
fmt.Println(strings.Contains("seafood", "foo")) // true
fmt.Println(strings.Contains("seafood", "bar")) // false
fmt.Println(strings.Contains("seafood", "")) // true
fmt.Println(strings.Contains("", "")) // true
複製代碼
ContainsAny
用於判斷子串中是否具備一個字符在源串s
中。子串爲空,返回false
。app
fmt.Println(strings.ContainsAny("team", "i")) // false
fmt.Println(strings.ContainsAny("fail", "ui")) // true
fmt.Println(strings.ContainsAny("ure", "ui")) // true
fmt.Println(strings.ContainsAny("failure", "ui")) // true
fmt.Println(strings.ContainsAny("foo", "")) // false
fmt.Println(strings.ContainsAny("", "")) // false
複製代碼
ContainsRune
用於判斷Ascall碼錶明的字符是否在源串s
中。函數
// Finds whether a string contains a particular Unicode code point.
// The code point for the lowercase letter "a", for example, is 97.
fmt.Println(strings.ContainsRune("aardvark", 97))
fmt.Println(strings.ContainsRune("timeout", 97))
複製代碼
判斷子串在源串中的數量,若是子串爲空,則長度爲源串的長度+1。測試
fmt.Println(strings.Count("cheese", "e")) // 3
fmt.Println(strings.Count("five", "")) // before & after each rune 5=4+1
複製代碼
在不區分大小寫的狀況下,判斷兩個字符串是否相同。ui
Fields
:使用空白分割字符串。 FieldsFunc
:根據傳入的函數分割字符串,若是當前參數c
不是數字或者字母,返回true
做爲分割符號。spa
fmt.Printf("Fields are: %q", strings.Fields(" foo bar baz ")) // ["foo" "bar" "baz"]
f := func(c rune) bool {
return !unicode.IsLetter(c) && !unicode.IsNumber(c)
}
fmt.Printf("Fields are: %q", strings.FieldsFunc(" foo1;bar2,baz3...", f)) // ["foo1" "bar2" "baz3"]
複製代碼
判斷字符串是不是以某個子串做爲開頭或者結尾。code
fmt.Println(strings.HasPrefix("Gopher", "Go")) // true
fmt.Println(strings.HasPrefix("Gopher", "C")) // false
fmt.Println(strings.HasPrefix("Gopher", "")) // true
fmt.Println(strings.HasSuffix("Amigo", "go")) // true
fmt.Println(strings.HasSuffix("Amigo", "O")) // false
fmt.Println(strings.HasSuffix("Amigo", "Ami")) // false
fmt.Println(strings.HasSuffix("Amigo", "")) // true
複製代碼
使用某個sep
,鏈接字符串。對象
s := []string{"foo", "bar", "baz"}
fmt.Println(strings.Join(s, ", ")) // foo,bar,baz
複製代碼
Index
,IndexAny
,IndexByte
,IndexFunc
,IndexRune
都是返回知足條件的第一個位置,若是沒有知足條件的數據,返回-1
。
fmt.Println(strings.Index("chicken", "ken")) // 4
fmt.Println(strings.Index("chicken", "dmr")) // -1
// 子串中的任意字符在源串出現的位置
fmt.Println(strings.IndexAny("chicken", "aeiouy")) // 2
fmt.Println(strings.IndexAny("crwth", "aeiouy")) // -1
// IndexByte,字符在字符串中出現的位置
fmt.Println(strings.IndexByte("golang", 'g')) // 0
fmt.Println(strings.IndexByte("gophers", 'h')) // 3
fmt.Println(strings.IndexByte("golang", 'x')) // -1
// IndexFunc 知足條件的做爲篩選條件
f := func(c rune) bool {
return unicode.Is(unicode.Han, c)
}
fmt.Println(strings.IndexFunc("Hello, 世界", f)) // 7
fmt.Println(strings.IndexFunc("Hello, world", f)) // -1
// 某個字符在源串中的位置
fmt.Println(strings.IndexRune("chicken", 'k')) // 4
fmt.Println(strings.IndexRune("chicken", 'd')) // -1
複製代碼
LastIndex
,LastIndexAny
,LastIndexByte
,LastIndexFunc
和Index
,IndexAny
,IndexByte
,IndexFunc
,IndexRune
用法保持一致,從右往前計數。
對字符串s
中每個字符執行map函數中的操做。
rot13 := func(r rune) rune { // r是遍歷的每個字符
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..."))
複製代碼
重複一下s
,count
是重複的次數,不能傳負數。
fmt.Println("ba" + strings.Repeat("na", 2))
複製代碼
使用new
來替換old
,替換的次數爲n
。若是n
爲負數,則替換全部的知足條件的子串。
fmt.Println(strings.Replace("oink oink oink", "k", "ky", 2)) // oinky oinkky oink
fmt.Println(strings.Replace("oink oink oink", "oink", "moo", -1)) moo moo moo
複製代碼
ReplaceAll
使用new
替換全部的old
,至關於使用Replace
時n<0
。
fmt.Printf("%q\n", strings.Split("a,b,c", ",")) // ["a","b","c"]
fmt.Printf("%q\n", strings.Split("a man a plan a canal panama", "a ")) // ["" "man " "plan " "canal panama"]
fmt.Printf("%q\n", strings.Split(" xyz ", "")) // [" " "x" "y" "z" " "]
fmt.Printf("%q\n", strings.Split("", "Bernardo O'Higgins")) // [""]
// SplitN 定義返回以後的切片中包含的長度,最後一部分是未被處理的。
fmt.Printf("%q\n", strings.SplitN("a,b,c", ",", 2)) // ["a", "b,c"]
z := strings.SplitN("a,b,c", ",", 0)
fmt.Printf("%q (nil = %v)\n", z, z == nil) // [] (nil = true)
// 使用sep分割,分割出來的字符串中包含sep,能夠限定分割以後返回的長度。
fmt.Printf("%q\n", strings.SplitAfterN("a,b,c", ",", 2)) // ["a,", "b,c"]
// 徹底分割
fmt.Printf("%q\n", strings.SplitAfter("a,b,c", ",")) // ["a,","b,", "c"]
複製代碼
對於SplitN
和SplitAfterN
的第二個n
說明。
n > 0: at most n substrings; the last substring will be the unsplit remainder.
n == 0: the result is nil (zero substrings)
n < 0: all substrings
複製代碼
// Trim 包含在cutset中的元素都會被去掉
fmt.Print(strings.Trim("¡¡¡Hello, Gophers!!!", "!¡")) // Hello, Gophers
// TrimFunc去掉知足條件的字符
fmt.Print(strings.TrimFunc("¡¡¡Hello, Gophers!!!", func(r rune) bool {
return !unicode.IsLetter(r) && !unicode.IsNumber(r)
}))
// TrimLeft 去掉左邊知足包含在cutset中的元素,直到遇到不在cutset中的元素爲止
fmt.Print(strings.TrimLeft("¡¡¡Hello, Gophers!!!", "!¡")) // Hello, Gophers!!!
// TrimLeftFunc 去掉左邊屬於函數返回值部分,直到遇到不在cutset中的元素爲止
fmt.Print(strings.TrimLeftFunc("¡¡¡Hello, Gophers!!!", func(r rune) bool {
return !unicode.IsLetter(r) && !unicode.IsNumber(r)
})) // Hello, Gophers!!!
// TrimPrefix 去掉開頭部分;TrimSuffix 去掉結尾部分
var s = "¡¡¡Hello, Gophers!!!"
s = strings.TrimPrefix(s, "¡¡¡Hello, ")
s = strings.TrimPrefix(s, "¡¡¡Howdy, ")
fmt.Print(s)
複製代碼
TrimRight
,TrimRightFunc
和TrimLeft
,TrimLeftFunc
功能保持一直,無需贅述。
A Builder is used to efficiently build a string using Write methods. It minimizes memory copying. The zero value is ready to use. Do not copy a non-zero Builder.
strings.Builder
使用Write
方法來高效的構建字符串。它最小化了內存拷貝,耗費零內存,不要拷貝非零的Builder
。
var b strings.Builder
for i := 3; i >= 1; i-- {
fmt.Fprintf(&b, "%d...", i)
}
b.WriteString("ignition")
fmt.Println(b.String())
複製代碼
輸出結果:
3...2...1...ignition
複製代碼
strings.Builder
做爲字符串拼接的利器,建議加大使用力度。
func (b *Builder) Cap() int // 容量,涉及批量內存分配機制 func (b *Builder) Grow(n int) // 手動分配內存數量 func (b *Builder) Len() int // 當前builder中含有的全部字符長度 func (b *Builder) Reset() // 清空builder func (b *Builder) String() string // 轉化爲字符串輸出 func (b *Builder) Write(p []byte) (int, error) // 往builder寫入數據 func (b *Builder) WriteByte(c byte) error // 往builder寫入數據 func (b *Builder) WriteRune(r rune) (int, error) // 往builder寫入數據 func (b *Builder) WriteString(s string) (int, error) // 往builder寫入數據 複製代碼
type Reader struct {
s string //對應的字符串
i int64 // 當前讀取到的位置
prevRune int
}
複製代碼
A Reader implements the io.Reader, io.ReaderAt, io.Seeker, io.WriterTo, io.ByteScanner, and io.RuneScanner interfaces by reading from a string. The zero value for Reader operates like a Reader of an empty string.
Reader
經過讀取字符串的方式,實現了接口io.Reader
, io.ReaderAt
, io.Seeker
, io.WriterTo
, io.ByteScanner
和io.RuneScanner
。零值Reader
操做起來就像操做空字符串的io.Reader
同樣。
func NewReader(s string) *Reader // 初始化reader實例 func (r *Reader) Len() int // 未讀字符長度 func (r *Reader) Read(b []byte) (n int, err error) func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) func (r *Reader) ReadByte() (byte, error) func (r *Reader) ReadRune() (ch rune, size int, err error) func (r *Reader) Reset(s string) // 重置以從s中讀 func (r *Reader) Seek(offset int64, whence int) (int64, error) // Seek implements the io.Seeker interface. func (r *Reader) Size() int64 // 字符串的原始長度 func (r *Reader) UnreadByte() error func (r *Reader) UnreadRune() error func (r *Reader) WriteTo(w io.Writer) (n int64, err error) // WriteTo implements the io.WriterTo interface. 複製代碼
Len做用: 返回未讀的字符串長度。
Size的做用:返回字符串的長度。
Read的做用: 讀取字符串信息,讀取以後會改變Len的返回值
r := strings.NewReader("abcdefghijklmn")
fmt.Println(r.Len()) // 輸出14 初始時,未讀長度等於字符串長度
var buf []byte
buf = make([]byte, 5)
readLen, err := r.Read(buf)
fmt.Println("讀取到的長度:", readLen) //讀取到的長度5
if err != nil {
fmt.Println("錯誤:", err)
}
fmt.Println(buf) //adcde
fmt.Println(r.Len()) //9 讀取到了5個 剩餘未讀是14-5
fmt.Println(r.Size()) //14 字符串的長度
複製代碼
讀取偏移off字節後的剩餘信息到b中,ReadAt函數不會影響Len的數值。
r := strings.NewReader("abcdefghijklmn")
var bufAt, buf []byte
buf = make([]byte, 5)
r.Read(buf)
fmt.Println("剩餘未讀的長度", r.Len()) //剩餘未讀的長度 9
fmt.Println("已讀取的內容", string(buf)) //已讀取的內容 abcde
bufAt = make([]byte, 256)
r.ReadAt(bufAt, 5)
fmt.Println(string(bufAt)) //fghijklmn
//測試下是否影響Len和Read方法
fmt.Println("剩餘未讀的長度", r.Len()) //剩餘未讀的長度 9
fmt.Println("已讀取的內容", string(buf)) //已讀取的內容 abcde
複製代碼
ReadByte從當前已讀取位置繼續讀取一個字節。
UnreadByte將當前已讀取位置回退一位,當前位置的字節標記成未讀取字節。
ReadByte
和UnreadByte
會改變reader對象的長度。
r := strings.NewReader("abcdefghijklmn")
//讀取一個字節
b, _ := r.ReadByte()
fmt.Println(string(b)) // a
//int(r.Size()) - r.Len() 已讀取字節數
fmt.Println(int(r.Size()) - r.Len()) // 1
//讀取一個字節
b, _ = r.ReadByte()
fmt.Println(string(b)) // b
fmt.Println(int(r.Size()) - r.Len()) // 2
//回退一個字節
r.UnreadByte()
fmt.Println(int(r.Size()) - r.Len()) // 1
//讀取一個字節
b, _ = r.ReadByte()
fmt.Println(string(b))
複製代碼
ReadAt
方法並不會改變Len()
的值,Seek
的移位操做能夠改變。offset
是偏移的位置,whence
是偏移起始位置,支持三種位置:io.SeekStart
起始位,io.SeekCurrent
當前位,io.SeekEnd
末位。 offset
能夠是負數,當時偏移起始位與offset相加獲得的值不能小於0或者大於size()的長度。
r := strings.NewReader("abcdefghijklmn")
var buf []byte
buf = make([]byte, 5)
r.Read(buf)
fmt.Println(string(buf), r.Len()) //adcde 9
buf = make([]byte, 5)
r.Seek(-2, io.SeekCurrent) //從當前位置向前偏移兩位 (5-2)
r.Read(buf)
fmt.Println(string(buf), r.Len()) //defgh 6
buf = make([]byte, 5)
r.Seek(-3, io.SeekEnd) //設置當前位置是末尾前移三位
r.Read(buf)
fmt.Println(string(buf), r.Len()) //lmn 0
buf = make([]byte, 5)
r.Seek(3, io.SeekStart) //設置當前位置是起始位後移三位
r.Read(buf)
fmt.Println(string(buf), r.Len()) //defgh 6
複製代碼