1. 程式人生 > 程式設計 >Go中strings的常用方法詳解

Go中strings的常用方法詳解

string操作在程式設計中具有極高的頻率,那麼string中有哪些有用的方法呢?

使用strings直接操作

Compare

  • func Compare(a,b string) int

按照字典序比較兩個字串,通常情況下直接使用=,>,<會更快一些。

Contains,ContainsAny 和 ContainsRune

  • func Contains(s,substr string) bool
  • func ContainsAny(s,chars string) bool
  • func ContainsRune(s string,r rune) bool

字串s中是否包含substr,返回true或者false。

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。

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))

Count

  • func Count(s,substr string) int

判斷子串在源串中的數量,如果子串為空,則長度為源串的長度+1。

fmt.Println(strings.Count("cheese","e")) // 3
fmt.Println(strings.Count("five","")) // before & after each rune 5=4+1

EqualFold

  • func EqualFold(s,t string) bool

在不區分大小寫的情況下,判斷兩個字串是否相同。

Fields

  • func Fields(s string) []string
  • func FieldsFunc(s string,f func(rune) bool) []string

Fields:使用空白分割字串。

FieldsFunc:根據傳入的函式分割字串,如果當前引數c不是數字或者字母,返回true作為分割符號。

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"]

HasPrefix 和 HasSuffix

  • func HasPrefix(s,prefix string) bool
  • func HasSuffix(s,suffix string) bool

判斷字串是否是以某個子串作為開頭或者結尾。

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 

Join

  • func Join(elems []string,sep string) string

使用某個sep,連線字串。

s := []string{"foo","bar","baz"}
fmt.Println(strings.Join(s,",")) // foo,bar,baz

Index,IndexAny,IndexByte,IndexFunc,IndexRune

  • func Index(s,substr string) int
  • func IndexAny(s,chars string) int
  • func IndexByte(s string,c byte) int
  • func IndexFunc(s string,f func(rune) bool) int
  • func IndexRune(s string,r rune) int

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

  • func LastIndex(s,substr string) int
  • func LastIndexAny(s,chars string) int
  • func LastIndexByte(s string,c byte) int
  • func LastIndexFunc(s string,f func(rune) bool) int

LastIndex,LastIndexAny,LastIndexByte,LastIndexFunc和Index,IndexAny,IndexByte,IndexFunc,IndexRune用法保持一致,從右往前計數。

Map

  • func Map(mapping func(rune) rune,s string) string

對字串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..."))

Repeat

  • func Repeat(s string,count int) string

重複一下s,count是重複的次數,不能傳負數。

fmt.Println("ba" + strings.Repeat("na",2))

Replace和ReplaceAll

  • func Replace(s,old,new string,n int) string
  • func ReplaceAll(s,new string) string

使用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。

Split,SplitN,SplitAfter和SplitAfterN

  • func Split(s,sep string) []string
  • func SplitAfter(s,sep string) []string
  • func SplitAfterN(s,sep string,n int) []string
  • func SplitN(s,n int) []string
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,2)) // ["a","b,c"]
z := strings.SplitN("a,0) 
fmt.Printf("%q (nil = %v)\n",z,z == nil) // [] (nil = true) 

// 使用sep分割,分割出來的字串中包含sep,可以限定分割之後返回的長度。
fmt.Printf("%q\n",strings.SplitAfterN("a,2)) // ["a,c"]

// 完全分割 
fmt.Printf("%q\n",strings.SplitAfter("a,")) // ["a,"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,TrimFunc,TrimLeft,TrimLeftFunc,TrimPrefix,TrimSuffix,TrimRight,TrimRightFunc

  • func Trim(s string,cutset string) string
  • func TrimFunc(s string,f func(rune) bool) string
  • func TrimLeft(s string,cutset string) string
  • func TrimLeftFunc(s string,f func(rune) bool) string
  • func TrimPrefix(s,prefix string) string
  • func TrimSuffix(s,suffix string) string
  • func TrimRight(s string,cutset string) string
  • func TrimRightFunc(s string,f func(rune) bool) string
// Trim 包含在cutset中的元素都會被去掉
fmt.Print(strings.Trim("¡¡¡Hello,Gophers!!!","!¡")) // Hello,Gophers

// TrimFunc去掉滿足條件的字元
fmt.Print(strings.TrimFunc("¡¡¡Hello,func(r rune) bool {
  return !unicode.IsLetter(r) && !unicode.IsNumber(r)
}))

// TrimLeft 去掉左邊滿足包含在cutset中的元素,直到遇到不在cutset中的元素為止
fmt.Print(strings.TrimLeft("¡¡¡Hello,Gophers!!!

// TrimLeftFunc 去掉左邊屬於函式返回值部分,直到遇到不在cutset中的元素為止
fmt.Print(strings.TrimLeftFunc("¡¡¡Hello,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功能保持一直,無需贅述。

使用strings.Builder操作

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寫入資料 

使用strings.Reader

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.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作用: 返回未讀的字串長度。
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  字串的長度

ReadAt

  • func (r *Reader) ReadAt(b []byte,err error)

讀取偏移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("剩餘未讀的長度",string(buf)) //已讀取的內容 abcde

ReadByte,UnreadByte

  • func (r *Reader) ReadByte() (byte,error)
  • func (r *Reader) UnreadByte() error

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)) 

Seek

  • func (r *Reader) Seek(offset int64,error)

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

到此這篇關於Go中strings的常用方法詳解的文章就介紹到這了,更多相關Go strings內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!