1. 程式人生 > 其它 >Golang語言社群--標準庫strings包講解

Golang語言社群--標準庫strings包講解

大家好,我是Golang語言社群主編彬哥,本篇文章是給大家轉載關於標準庫strings包的知識。

// Count 計算字串 sep 在 s 中的非重疊個數

// 如果 sep 為空字串,則返回 s 中的字元(非位元組)個數 + 1

// 使用 Rabin-Karp 演算法實現

func Count(s, sep string) int

func main() {
s := "Hello,世界!!!!!"
n := strings.Count(s, "!")
fmt.Println(n) // 5
n = strings.Count(s, "!!")
fmt.Println(n) // 2
}

------------------------------------------------------------

// Contains 判斷字串 s 中是否包含子串 substr

// 如果 substr 為空,則返回 true

func Contains(s, substr string) bool

func main() {
s := "Hello,世界!!!!!"
b := strings.Contains(s, "!!")
fmt.Println(b) // true
b = strings.Contains(s, "!?")
fmt.Println(b) // false
b = strings.Contains(s, "")
fmt.Println(b) // true
}

------------------------------------------------------------

// ContainsAny 判斷字串 s 中是否包含 chars 中的任何一個字元

// 如果 chars 為空,則返回 false

func ContainsAny(s, chars string) bool

func main() {
s := "Hello,世界!"
b := strings.ContainsAny(s, "abc")
fmt.Println(b) // false
b = strings.ContainsAny(s, "def")
fmt.Println(b) // true
b = strings.Contains(s, "")
fmt.Println(b) // true
}

------------------------------------------------------------

// ContainsRune 判斷字串 s 中是否包含字元 r

func ContainsRune(s string, r rune) bool

func main() {
	s := "Hello,世界!"
	b := strings.ContainsRune(s, 'n')
	fmt.Println(b) // false
	b = strings.ContainsRune(s, '界')
	fmt.Println(b) // true
	b = strings.ContainsRune(s, 0)
	fmt.Println(b) // false
}

------------------------------------------------------------

// Index 返回子串 sep 在字串 s 中第一次出現的位置

// 如果找不到,則返回 -1,如果 sep 為空,則返回 0。

// 使用 Rabin-Karp 演算法實現

func Index(s, sep string) int

func main() {
	s := "Hello,世界!"
	i := strings.Index(s, "h")
	fmt.Println(i) // -1
	i = strings.Index(s, "!")
	fmt.Println(i) // 12
	i = strings.Index(s, "")
	fmt.Println(i) // 0
}

------------------------------------------------------------

// LastIndex 返回子串 sep 在字串 s 中最後一次出現的位置

// 如果找不到,則返回 -1,如果 sep 為空,則返回字串的長度

// 使用樸素字串比較演算法實現

func LastIndex(s, sep string) int

func main() {
	s := "Hello,世界! Hello!"
	i := strings.LastIndex(s, "h")
	fmt.Println(i) // -1
	i = strings.LastIndex(s, "H")
	fmt.Println(i) // 14
	i = strings.LastIndex(s, "")
	fmt.Println(i) // 20
}

------------------------------------------------------------

// IndexRune 返回字元 r 在字串 s 中第一次出現的位置

// 如果找不到,則返回 -1

func IndexRune(s string, r rune) int

func main() {
	s := "Hello,世界! Hello!"
	i := strings.IndexRune(s, 'n')
	fmt.Println(i) // -1
	i = strings.IndexRune(s, '界')
	fmt.Println(i) // 9
	i = strings.IndexRune(s, 0)
	fmt.Println(i) // -1
}

------------------------------------------------------------

// IndexAny 返回字串 chars 中的任何一個字元在字串 s 中第一次出現的位置

// 如果找不到,則返回 -1,如果 chars 為空,則返回 -1

func IndexAny(s, chars string) int

func main() {
	s := "Hello,世界! Hello!"
	i := strings.IndexAny(s, "abc")
	fmt.Println(i) // -1
	i = strings.IndexAny(s, "dof")
	fmt.Println(i) // 1
	i = strings.IndexAny(s, "")
	fmt.Println(i) // -1
}

------------------------------------------------------------

// LastIndexAny 返回字串 chars 中的任何一個字元在字串 s 中最後一次出現的位置

// 如果找不到,則返回 -1,如果 chars 為空,也返回 -1

func LastIndexAny(s, chars string) int

func main() {
	s := "Hello,世界! Hello!"
	i := strings.LastIndexAny(s, "abc")
	fmt.Println(i) // -1
	i = strings.LastIndexAny(s, "def")
	fmt.Println(i) // 15
	i = strings.LastIndexAny(s, "")
	fmt.Println(i) // -1
}

------------------------------------------------------------

// SplitN 以 sep 為分隔符,將 s 切分成多個子串,結果中不包含 sep 本身

// 如果 sep 為空,則將 s 切分成 Unicode 字元列表。

// 如果 s 中沒有 sep 子串,則將整個 s 作為 []string 的第一個元素返回

// 引數 n 表示最多切分出幾個子串,超出的部分將不再切分。

// 如果 n 為 0,則返回 nil,如果 n 小於 0,則不限制切分個數,全部切分

func SplitN(s, sep string, n int) []string

func main() {
	s := "Hello, 世界! Hello!"
	ss := strings.SplitN(s, " ", 2)
	fmt.Printf("%qn", ss) // ["Hello," "世界! Hello!"]
	ss = strings.SplitN(s, " ", -1)
	fmt.Printf("%qn", ss) // ["Hello," "世界!" "Hello!"]
	ss = strings.SplitN(s, "", 3)
	fmt.Printf("%qn", ss) // ["H" "e" "llo, 世界! Hello!"]
}

------------------------------------------------------------

// SplitAfterN 以 sep 為分隔符,將 s 切分成多個子串,結果中包含 sep 本身

// 如果 sep 為空,則將 s 切分成 Unicode 字元列表。

// 如果 s 中沒有 sep 子串,則將整個 s 作為 []string 的第一個元素返回

// 引數 n 表示最多切分出幾個子串,超出的部分將不再切分。

// 如果 n 為 0,則返回 nil,如果 n 小於 0,則不限制切分個數,全部切分

func SplitAfterN(s, sep string, n int) []string

func main() {
	s := "Hello, 世界! Hello!"
	ss := strings.SplitAfterN(s, " ", 2)
	fmt.Printf("%qn", ss) // ["Hello, " "世界! Hello!"]
	ss = strings.SplitAfterN(s, " ", -1)
	fmt.Printf("%qn", ss) // ["Hello, " "世界! " "Hello!"]
	ss = strings.SplitAfterN(s, "", 3)
	fmt.Printf("%qn", ss) // ["H" "e" "llo, 世界! Hello!"]
}

------------------------------------------------------------

// Split 以 sep 為分隔符,將 s 切分成多個子切片,結果中不包含 sep 本身

// 如果 sep 為空,則將 s 切分成 Unicode 字元列表。

// 如果 s 中沒有 sep 子串,則將整個 s 作為 []string 的第一個元素返回

func Split(s, sep string) []string

func main() {
	s := "Hello, 世界! Hello!"
	ss := strings.Split(s, " ")
	fmt.Printf("%qn", ss) // ["Hello," "世界!" "Hello!"]
	ss = strings.Split(s, ", ")
	fmt.Printf("%qn", ss) // ["Hello" "世界! Hello!"]
	ss = strings.Split(s, "")
	fmt.Printf("%qn", ss) // 單個字元列表
}

------------------------------------------------------------

// SplitAfter 以 sep 為分隔符,將 s 切分成多個子切片,結果中包含 sep 本身

// 如果 sep 為空,則將 s 切分成 Unicode 字元列表。

// 如果 s 中沒有 sep 子串,則將整個 s 作為 []string 的第一個元素返回

func SplitAfter(s, sep string) []string

func main() {
	s := "Hello, 世界! Hello!"
	ss := strings.SplitAfter(s, " ")
	fmt.Printf("%qn", ss) // ["Hello, " "世界! " "Hello!"]
	ss = strings.SplitAfter(s, ", ")
	fmt.Printf("%qn", ss) // ["Hello, " "世界! Hello!"]
	ss = strings.SplitAfter(s, "")
	fmt.Printf("%qn", ss) // 單個字元列表
}

------------------------------------------------------------

// Fields 以連續的空白字元為分隔符,將 s 切分成多個子串,結果中不包含空白字元本身

// 空白字元有:t, n, v, f, r, ' ', U+0085 (NEL), U+00A0 (NBSP)

// 如果 s 中只包含空白字元,則返回一個空列表

func Fields(s string) []string

func main() {
	s := "Hello, 世界! Hello!"
	ss := strings.Fields(s)
	fmt.Printf("%qn", ss) // ["Hello," "世界!" "Hello!"]
}

------------------------------------------------------------

// FieldsFunc 以一個或多個滿足 f(rune) 的字元為分隔符,

// 將 s 切分成多個子串,結果中不包含分隔符本身。

// 如果 s 中沒有滿足 f(rune) 的字元,則返回一個空列表。

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

func isSlash(r rune) bool {
	return r == '\' || r == '/'
}

func main() {
	s := "C:\Windows\System32\FileName"
	ss := strings.FieldsFunc(s, isSlash)
	fmt.Printf("%qn", ss) // ["C:" "Windows" "System32" "FileName"]
}

------------------------------------------------------------

// Join 將 a 中的子串連線成一個單獨的字串,子串之間用 sep 分隔

func Join(a []string, sep string) string

func main() {
	ss := []string{"Monday", "Tuesday", "Wednesday"}
	s := strings.Join(ss, "|")
	fmt.Println(s)
}

------------------------------------------------------------

// HasPrefix 判斷字串 s 是否以 prefix 開頭

func HasPrefix(s, prefix string) bool

func main() {
	s := "Hello 世界!"
	b := strings.HasPrefix(s, "hello")
	fmt.Println(b) // false
	b = strings.HasPrefix(s, "Hello")
	fmt.Println(b) // true
}

------------------------------------------------------------

// HasSuffix 判斷字串 s 是否以 prefix 結尾

func HasSuffix(s, suffix string) bool

func main() {
	s := "Hello 世界!"
	b := strings.HasSuffix(s, "世界")
	fmt.Println(b) // false
	b = strings.HasSuffix(s, "世界!")
	fmt.Println(b) // true
}

------------------------------------------------------------

// Map 將 s 中滿足 mapping(rune) 的字元替換為 mapping(rune) 的返回值。

// 如果 mapping(rune) 返回負數,則相應的字元將被刪除。

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

func Slash(r rune) rune {
	if r == '\' {
		return '/'
	}
	return r
}
func main() {

	s := "C:\Windows\System32\FileName"
	ms := strings.Map(Slash, s)
	fmt.Printf("%qn", ms) // "C:/Windows/System32/FileName"
}

------------------------------------------------------------

// Repeat 將 count 個字串 s 連線成一個新的字串

func Repeat(s string, count int) string

func main() {
	s := "Hello!"
	rs := strings.Repeat(s, 3)
	fmt.Printf("%qn", rs) // "Hello!Hello!Hello!"
}

------------------------------------------------------------

// ToUpper 將 s 中的所有字元修改為其大寫格式

// 對於非 ASCII 字元,它的大寫格式需要查錶轉換

func ToUpper(s string) string

// ToLower 將 s 中的所有字元修改為其小寫格式

// 對於非 ASCII 字元,它的小寫格式需要查錶轉換

func ToLower(s string) string

// ToTitle 將 s 中的所有字元修改為其 Title 格式

// 大部分字元的 Title 格式就是其 Upper 格式

// 只有少數字符的 Title 格式是特殊字元

// 這裡的 ToTitle 主要給 Title 函式呼叫

func ToTitle(s string) string

func main() {
	s := "heLLo worLd Abc"
	us := strings.ToUpper(s)
	ls := strings.ToLower(s)
	ts := strings.ToTitle(s)
	fmt.Printf("%qn", us) // "HELLO WORLD ABC"
	fmt.Printf("%qn", ls) // "hello world abc"
	fmt.Printf("%qn", ts) // "HELLO WORLD ABC"
}

// 獲取非 ASCII 字元的 Title 格式列表

func main() {
	for _, cr := range unicode.CaseRanges {
		// u := uint32(cr.Delta[unicode.UpperCase]) // 大寫格式
		// l := uint32(cr.Delta[unicode.LowerCase]) // 小寫格式
		t := uint32(cr.Delta[unicode.TitleCase]) // Title 格式
		// if t != 0 && t != u {
		if t != 0 {
			for i := cr.Lo; i <= cr.Hi; i++ {
				fmt.Printf("%c -> %cn", i, i+t)
			}
		}
	}
}

------------------------------------------------------------

// ToUpperSpecial 將 s 中的所有字元修改為其大寫格式。

// 優先使用 _case 中的規則進行轉換

func ToUpperSpecial(_case unicode.SpecialCase, s string) string

// ToLowerSpecial 將 s 中的所有字元修改為其小寫格式。

// 優先使用 _case 中的規則進行轉換

func ToLowerSpecial(_case unicode.SpecialCase, s string) string

// ToTitleSpecial 將 s 中的所有字元修改為其 Title 格式。

// 優先使用 _case 中的規則進行轉換

func ToTitleSpecial(_case unicode.SpecialCase, s string) string

_case 規則說明,以下列語句為例:

unicode.CaseRange{'A', 'Z', [unicode.MaxCase]rune{3, -3, 0}}

·其中 'A', 'Z' 表示此規則隻影響 'A' 到 'Z' 之間的字元。

·其中 [unicode.MaxCase]rune 陣列表示:

當使用 ToUpperSpecial 轉換時,將字元的 Unicode 編碼與第一個元素值(3)相加

當使用 ToLowerSpecial 轉換時,將字元的 Unicode 編碼與第二個元素值(-3)相加

當使用 ToTitleSpecial 轉換時,將字元的 Unicode 編碼與第三個元素值(0)相加

func main() {
	// 定義轉換規則
	var _MyCase = unicode.SpecialCase{
		// 將半形逗號替換為全形逗號,ToTitle 不處理
		unicode.CaseRange{',', ',',
			[unicode.MaxCase]rune{',' - ',', ',' - ',', 0}},
		// 將半形句號替換為全形句號,ToTitle 不處理
		unicode.CaseRange{'.', '.',
			[unicode.MaxCase]rune{'。' - '.', '。' - '.', 0}},
		// 將 ABC 分別替換為全形的 ABC、abc,ToTitle 不處理
		unicode.CaseRange{'A', 'C',
			[unicode.MaxCase]rune{'A' - 'A', 'a' - 'A', 0}},
	}
	s := "ABCDEF,abcdef."
	us := strings.ToUpperSpecial(_MyCase, s)
	fmt.Printf("%qn", us) // "ABCDEF,ABCDEF。"
	ls := strings.ToLowerSpecial(_MyCase, s)
	fmt.Printf("%qn", ls) // "abcdef,abcdef。"
	ts := strings.ToTitleSpecial(_MyCase, s)
	fmt.Printf("%qn", ts) // "ABCDEF,ABCDEF."
}

------------------------------------------------------------

// Title 將 s 中的所有單詞的首字母修改為其 Title 格式

// BUG: Title 規則不能正確處理 Unicode 標點符號

func Title(s string) string

func main() {
	s := "heLLo worLd"
	ts := strings.Title(s)
	fmt.Printf("%qn", ts) // "HeLLo WorLd"
}

------------------------------------------------------------

// TrimLeftFunc 將刪除 s 頭部連續的滿足 f(rune) 的字元

func TrimLeftFunc(s string, f func(rune) bool) string

------------------------------------------------------------

// TrimRightFunc 將刪除 s 尾部連續的滿足 f(rune) 的字元

func TrimRightFunc(s string, f func(rune) bool) string

func isSlash(r rune) bool {
	return r == '\' || r == '/'
}

func main() {
	s := "\\HostName\C\Windows\"
	ts := strings.TrimRightFunc(s, isSlash)
	fmt.Printf("%qn", ts) // "\\HostName\C\Windows"
}

------------------------------------------------------------

// TrimFunc 將刪除 s 首尾連續的滿足 f(rune) 的字元

func TrimFunc(s string, f func(rune) bool) string

func isSlash(r rune) bool {
    return r == '\' || r == '/'
}
func main() {
    s := "\\HostName\C\Windows\"
    ts := strings.TrimFunc(s, isSlash)
    fmt.Printf("%qn", ts) // "HostName\C\Windows"
}

------------------------------------------------------------

// 返回 s 中第一個滿足 f(rune) 的字元的位元組位置。

// 如果沒有滿足 f(rune) 的字元,則返回 -1

func IndexFunc(s string, f func(rune) bool) int

func isSlash(r rune) bool {
	return r == '\' || r == '/'
}

func main() {
	s := "C:\Windows\System32"
	i := strings.IndexFunc(s, isSlash)
	fmt.Printf("%vn", i) // 2
}

------------------------------------------------------------

// 返回 s 中最後一個滿足 f(rune) 的字元的位元組位置。

// 如果沒有滿足 f(rune) 的字元,則返回 -1

func LastIndexFunc(s string, f func(rune) bool) int

func isSlash(r rune) bool {
	return r == '\' || r == '/'
}

func main() {
	s := "C:\Windows\System32"
	i := strings.LastIndexFunc(s, isSlash)
	fmt.Printf("%vn", i) // 10
}

------------------------------------------------------------

// Trim 將刪除 s 首尾連續的包含在 cutset 中的字元

func Trim(s string, cutset string) string

func main() {
	s := " Hello 世界! "
	ts := strings.Trim(s, " Helo!")
	fmt.Printf("%qn", ts) // "世界"
}

------------------------------------------------------------

// TrimLeft 將刪除 s 頭部連續的包含在 cutset 中的字元

func TrimLeft(s string, cutset string) string

func main() {
	s := " Hello 世界! "
	ts := strings.TrimLeft(s, " Helo")
	fmt.Printf("%qn", ts) // "世界! "
}

------------------------------------------------------------

// TrimRight 將刪除 s 尾部連續的包含在 cutset 中的字元

func TrimRight(s string, cutset string) string

func main() {
	s := " Hello 世界! "
	ts := strings.TrimRight(s, " 世界!")
	fmt.Printf("%qn", ts) // " Hello"
}

------------------------------------------------------------

// TrimSpace 將刪除 s 首尾連續的的空白字元

func TrimSpace(s string) string

func main() {
	s := " Hello 世界! "
	ts := strings.TrimSpace(s)
	fmt.Printf("%qn", ts) // "Hello 世界!"
}

------------------------------------------------------------

// TrimPrefix 刪除 s 頭部的 prefix 字串

// 如果 s 不是以 prefix 開頭,則返回原始 s

func TrimPrefix(s, prefix string) string

func main() {
	s := "Hello 世界!"
	ts := strings.TrimPrefix(s, "Hello")
	fmt.Printf("%qn", ts) // " 世界"
}

------------------------------------------------------------

// TrimSuffix 刪除 s 尾部的 suffix 字串

// 如果 s 不是以 suffix 結尾,則返回原始 s

func TrimSuffix(s, suffix string) string

func main() {
	s := "Hello 世界!!!!!"
	ts := strings.TrimSuffix(s, "!!!!")
	fmt.Printf("%qn", ts) // " 世界"
}

注:TrimSuffix只是去掉s字串結尾的suffix字串,只是去掉1次,而TrimRight是一直去掉s字串右邊的字串,只要有響應的字串就去掉,是一個多次的過程,這也是二者的本質區別.

------------------------------------------------------------ // Replace 返回 s 的副本,並將副本中的 old 字串替換為 new 字串 // 替換次數為 n 次,如果 n 為 -1,則全部替換 // 如果 old 為空,則在副本的每個字元之間都插入一個 new func Replace(s, old, new string, n int) string

func main() {
	s := "Hello 世界!"
	s = strings.Replace(s, " ", ",", -1)
	fmt.Println(s)
	s = strings.Replace(s, "", "|", -1)
	fmt.Println(s)
}

------------------------------------------------------------

// EqualFold 判斷 s 和 t 是否相等。忽略大小寫,同時它還會對特殊字元進行轉換

// 比如將“ϕ”轉換為“Φ”、將“DŽ”轉換為“Dž”等,然後再進行比較

func EqualFold(s, t string) bool

func main() {
	s1 := "Hello 世界! ϕ DŽ"
	s2 := "hello 世界! Φ Dž"
	b := strings.EqualFold(s1, s2)
	fmt.Printf("%vn", b) // true
}

// reader.go

------------------------------------------------------------

// Reader 結構通過讀取字串,實現了 io.Reader,io.ReaderAt,

// io.Seeker,io.WriterTo,io.ByteScanner,io.RuneScanner 介面

type Reader struct {

s string // 要讀取的字串

i int // 當前讀取的索引位置,從 i 處開始讀取資料

prevRune int // 讀取的前一個字元的索引位置,小於 0 表示之前未讀取字元

}

// 通過字串 s 建立 strings.Reader 物件

// 這個函式類似於 bytes.NewBufferString

// 但比 bytes.NewBufferString 更有效率,而且只讀

func NewReader(s string) *Reader { return &Reader{s, 0, -1} }

------------------------------------------------------------

// Len 返回 r.i 之後的所有資料的位元組長度

func (r *Reader) Len() int

func main() {
	s := "Hello 世界!"
	// 建立 Reader
	r := strings.NewReader(s)
	// 獲取字串的編碼長度
	fmt.Println(r.Len()) // 13
}

------------------------------------------------------------

// Read 將 r.i 之後的所有資料寫入到 b 中(如果 b 的容量足夠大)

// 返回讀取的位元組數和讀取過程中遇到的錯誤

// 如果無可讀資料,則返回 io.EOF

func (r *Reader) Read(b []byte) (n int, err error)

func main() {
	s := "Hello World!"
	// 建立 Reader
	r := strings.NewReader(s)
	// 建立長度為 5 個位元組的緩衝區
	b := make([]byte, 5)
	// 迴圈讀取 r 中的字串
	for n, _ := r.Read(b); n > 0; n, _ = r.Read(b) {
		fmt.Printf("%q, ", b[:n]) // "Hello", " Worl", "d!"
	}
}

------------------------------------------------------------

// ReadAt 將 off 之後的所有資料寫入到 b 中(如果 b 的容量足夠大)

// 返回讀取的位元組數和讀取過程中遇到的錯誤

// 如果無可讀資料,則返回 io.EOF

// 如果資料被一次性讀取完畢,則返回 io.EOF

func (r *Reader) ReadAt(b []byte, off int64) (n int, err error)

func main() {
	s := "Hello World!"
	// 建立 Reader
	r := strings.NewReader(s)
	// 建立長度為 5 個位元組的緩衝區
	b := make([]byte, 5)
	// 讀取 r 中指定位置的字串
	n, _ := r.ReadAt(b, 0)
	fmt.Printf("%qn", b[:n]) // "Hello"
	// 讀取 r 中指定位置的字串
	n, _ = r.ReadAt(b, 6)
	fmt.Printf("%qn", b[:n]) // "World"
}

------------------------------------------------------------

// ReadByte 將 r.i 之後的一個位元組寫入到返回值 b 中

// 返回讀取的位元組和讀取過程中遇到的錯誤

// 如果無可讀資料,則返回 io.EOF

func (r *Reader) ReadByte() (b byte, err error)

func main() {
	s := "Hello World!"
	// 建立 Reader
	r := strings.NewReader(s)
	// 讀取 r 中的一個位元組
	for i := 0; i < 3; i++ {
		b, _ := r.ReadByte()
		fmt.Printf("%q, ", b) // 'H', 'e', 'l',
	}
}

------------------------------------------------------------

// UnreadByte 撤消前一次的 ReadByte 操作,即 r.i--

func (r *Reader) UnreadByte() error

func main() {
	s := "Hello World!"
	// 建立 Reader
	r := strings.NewReader(s)
	// 讀取 r 中的一個位元組
	for i := 0; i < 3; i++ {
		b, _ := r.ReadByte()
		fmt.Printf("%q, ", b) // 'H', 'H', 'H',
		r.UnreadByte()        // 撤消前一次的位元組讀取操作
	}
}

------------------------------------------------------------

// ReadRune 將 r.i 之後的一個字元寫入到返回值 ch 中

// ch: 讀取的字元

// size:ch 的編碼長度

// err: 讀取過程中遇到的錯誤

// 如果無可讀資料,則返回 io.EOF

// 如果 r.i 之後不是一個合法的 UTF-8 字元編碼,則返回 utf8.RuneError 字元

func (r *Reader) ReadRune() (ch rune, size int, err error)

func main() {
	s := "你好 世界!"
	// 建立 Reader
	r := strings.NewReader(s)
	// 讀取 r 中的一個字元
	for i := 0; i < 5; i++ {
		b, n, _ := r.ReadRune()
		fmt.Printf(`"%c:%v", `, b, n)
		// "你:3", "好:3", " :1", "世:3", "界:3",
	}
}

------------------------------------------------------------

// 撤消前一次的 ReadRune 操作

func (r *Reader) UnreadRune() error

func main() {
	s := "你好 世界!"
	// 建立 Reader
	r := strings.NewReader(s)
	// 讀取 r 中的一個字元
	for i := 0; i < 5; i++ {
		b, _, _ := r.ReadRune()
		fmt.Printf("%q, ", b)
		// '你', '你', '你', '你', '你',
		r.UnreadRune() // 撤消前一次的字元讀取操作
	}
}

------------------------------------------------------------

// Seek 用來移動 r 中的索引位置

// offset:要移動的偏移量,負數表示反向移動

// whence:從那裡開始移動,0:起始位置,1:當前位置,2:結尾位置

// 如果 whence 不是 0、1、2,則返回錯誤資訊

// 如果目標索引位置超出字串範圍,則返回錯誤資訊

// 目標索引位置不能超出 1 << 31,否則返回錯誤資訊

func (r *Reader) Seek(offset int64, whence int) (int64, error)

func main() {
	s := "Hello World!"
	// 建立 Reader
	r := strings.NewReader(s)
	// 建立讀取緩衝區
	b := make([]byte, 5)
	// 讀取 r 中指定位置的內容
	r.Seek(6, 0) // 移動索引位置到第 7 個位元組
	r.Read(b)    // 開始讀取
	fmt.Printf("%qn", b)
	r.Seek(-5, 1) // 將索引位置移回去
	r.Read(b)     // 繼續讀取
	fmt.Printf("%qn", b)
}

------------------------------------------------------------

// WriteTo 將 r.i 之後的資料寫入介面 w 中

func (r *Reader) WriteTo(w io.Writer) (n int64, err error)

func main() {
	s := "Hello World!"
	// 建立 Reader
	r := strings.NewReader(s)
	// 建立 bytes.Buffer 物件,它實現了 io.Writer 介面
	buf := bytes.NewBuffer(nil)
	// 將 r 中的資料寫入 buf 中
	r.WriteTo(buf)
	fmt.Printf("%qn", buf) // "Hello World!"
}

============================================================

// replace.go

------------------------------------------------------------

// Replacer 根據一個替換列表執行替換操作

type Replacer struct {

Replace(s string) string

WriteString(w io.Writer, s string) (n int, err error)

}

------------------------------------------------------------

// NewReplacer 通過“替換列表”建立一個 Replacer 物件。

// 按照“替換列表”中的順序進行替換,只替換非重疊部分。

// 如果引數的個數不是偶數,則丟擲異常。

// 如果在“替換列表”中有相同的“查詢項”,則後面重複的“查詢項”會被忽略

func NewReplacer(oldnew ...string) *Replacer

------------------------------------------------------------

// Replace 返回對 s 進行“查詢和替換”後的結果

// Replace 使用的是 Boyer-Moore 演算法,速度很快

func (r *Replacer) Replace(s string) string

func main() {
	srp := strings.NewReplacer("Hello", "你好", "World", "世界", "!", "!")
	s := "Hello World!Hello World!hello world!"
	rst := srp.Replace(s)
	fmt.Print(rst) // 你好 世界!你好 世界!hello world!
}
<span style="color:#FF0000;">注:這兩種寫法均可.</span>
func main() {

	wl := []string{"Hello", "Hi", "Hello", "你好"}
	srp := strings.NewReplacer(wl...)
	s := "Hello World! Hello World! hello world!"
	rst := srp.Replace(s)
	fmt.Print(rst) // Hi World! Hi World! hello world!
}

------------------------------------------------------------

// WriteString 對 s 進行“查詢和替換”,然後將結果寫入 w 中

func (r *Replacer) WriteString(w io.Writer, s string) (n int, err error)

func main() {
	wl := []string{"Hello", "你好", "World", "世界", "!", "!"}
	srp := strings.NewReplacer(wl...)
	s := "Hello World!Hello World!hello world!"
	srp.WriteString(os.Stdout, s)
	// 你好 世界!你好 世界!hello world!
}