鍍金池/ 教程/ GO/ 4.6 字符串
4.7 strings 和 strconv 包
13.6 啟動(dòng)外部命令和程序
?# 11.4 類型判斷:type-switch
12.1 讀取用戶的輸入
10.6 方法
12.2 文件讀寫
13 錯(cuò)誤處理與測(cè)試
9.3 鎖和 sync 包
12.3 文件拷貝
?# 11.7 第一個(gè)例子:使用 Sorter 接口排序
?# 11.5 測(cè)試一個(gè)值是否實(shí)現(xiàn)了某個(gè)接口
6.4 defer 和追蹤
12.10 XML 數(shù)據(jù)格式
13.10 性能調(diào)試:分析并優(yōu)化 Go 程序
?# 11.1 接口是什么
2.2 Go 環(huán)境變量
2.6 安裝目錄清單
2.5 在 Windows 上安裝 Go
11.11 Printf 和反射
1.2 語(yǔ)言的主要特性與發(fā)展的環(huán)境和影響因素
9.0 包(package)
7.4 切片重組(reslice)
13.2 運(yùn)行時(shí)異常和 panic
10.2 使用工廠方法創(chuàng)建結(jié)構(gòu)體實(shí)例
12.8 使用接口的實(shí)際例子:fmt.Fprintf
2.4 在 Mac OS X 上安裝 Go
3.8 Go 性能說(shuō)明
7.2 切片
8.0 Map
3.1 Go 開發(fā)環(huán)境的基本要求
5.6 標(biāo)簽與 goto
6.10 使用閉包調(diào)試
9.5 自定義包和可見(jiàn)性
4.3 常量
?# 11.2 接口嵌套接口
6.5 內(nèi)置函數(shù)
前言
10.8 垃圾回收和 SetFinalizer
2.8 Go 解釋器
13.7 Go 中的單元測(cè)試和基準(zhǔn)測(cè)試
6.8 閉包
4.9 指針
13.1 錯(cuò)誤處理
10.1 結(jié)構(gòu)體定義
5.1 if-else 結(jié)構(gòu)
6.6 遞歸函數(shù)
9.9 通過(guò) Git 打包和安裝
2.7 Go 運(yùn)行時(shí)(runtime)
10.7 類型的 String() 方法和格式化描述符
3.7 其它工具
9.6 為自定義包使用 godoc
11.12 接口與動(dòng)態(tài)類型
13.3 從 panic 中恢復(fù)(Recover)
10.3 使用自定義包中的結(jié)構(gòu)體
11.14 結(jié)構(gòu)體、集合和高階函數(shù)
3.6 生成代碼文檔
9.2 regexp 包
4.1 文件名、關(guān)鍵字與標(biāo)識(shí)符
?# 11.6 使用方法集與接口
7.0 數(shù)組與切片
7.1 聲明和初始化
12.11 用 Gob 傳輸數(shù)據(jù)
5.5 Break 與 continue
1.1 起源與發(fā)展
?# 11 接口(Interfaces)與反射(reflection)
6.9 應(yīng)用閉包:將函數(shù)作為返回值
4.2 Go 程序的基本結(jié)構(gòu)和要素
8.6 將 map 的鍵值對(duì)調(diào)
6.11 計(jì)算函數(shù)執(zhí)行時(shí)間
5.0 控制結(jié)構(gòu)
10.5 匿名字段和內(nèi)嵌結(jié)構(gòu)體
4.6 字符串
3.0 編輯器、集成開發(fā)環(huán)境與其它工具
13.8 測(cè)試的具體例子
7.6 字符串、數(shù)組和切片的應(yīng)用
8.4 map 類型的切片
3.9 與其它語(yǔ)言進(jìn)行交互
7.3 For-range 結(jié)構(gòu)
9.7 使用 go install 安裝自定義包
6.0 函數(shù)
9.8 自定義包的目錄結(jié)構(gòu)、go install 和 go test
6.3 傳遞變長(zhǎng)參數(shù)
13.9 用(測(cè)試數(shù)據(jù))表驅(qū)動(dòng)測(cè)試
11.9 空接口
8.1 聲明、初始化和 make
6.2 函數(shù)參數(shù)與返回值
9.11 在 Go 程序中使用外部庫(kù)
3.3 調(diào)試器
4.5 基本類型和運(yùn)算符
?# 11.8 第二個(gè)例子:讀和寫
12.5 用 buffer 讀取文件
總結(jié):Go 中的面向?qū)ο?/span>
11.10 反射包
12.7 用 defer 關(guān)閉文件
9.4 精密計(jì)算和 big 包
4.4 變量
6.1 介紹
13.4 自定義包中的錯(cuò)誤處理和 panicking
12.4 從命令行讀取參數(shù)
9.10 Go 的外部包和項(xiàng)目
8.3 for-range 的配套用法
3.5 格式化代碼
10.4 帶標(biāo)簽的結(jié)構(gòu)體
7.5 切片的復(fù)制與追加
?# 11.3 類型斷言:如何檢測(cè)和轉(zhuǎn)換接口變量的類型
5.4 for 結(jié)構(gòu)
4.8 時(shí)間和日期
2.3 在 Linux 上安裝 Go
12 讀寫數(shù)據(jù)
6.12 通過(guò)內(nèi)存緩存來(lái)提升性能
9.1 標(biāo)準(zhǔn)庫(kù)概述
12.6 用切片讀寫文件
10 結(jié)構(gòu)(struct)與方法(method)
8.5 map 的排序
12.9 JSON 數(shù)據(jù)格式
13.5 一種用閉包處理錯(cuò)誤的模式
3.2 編輯器和集成開發(fā)環(huán)境
12.12 Go 中的密碼學(xué)
5.2 測(cè)試多返回值函數(shù)的錯(cuò)誤
6.7 將函數(shù)作為參數(shù)
8.2 測(cè)試鍵值對(duì)是否存在及刪除元素
3.4 構(gòu)建并運(yùn)行 Go 程序
2.1 平臺(tái)與架構(gòu)
5.3 switch 結(jié)構(gòu)

4.6 字符串

字符串是 UTF-8 字符的一個(gè)序列(當(dāng)字符為 ASCII 碼時(shí)則占用 1 個(gè)字節(jié),其它字符根據(jù)需要占用 2-4 個(gè)字節(jié))。UTF-8 是被廣泛使用的編碼格式,是文本文件的標(biāo)準(zhǔn)編碼,其它包括 XML 和 JSON 在內(nèi),也都使用該編碼。由于該編碼對(duì)占用字節(jié)長(zhǎng)度的不定性,Go 中的字符串也可能根據(jù)需要占用 1 至 4 個(gè)字節(jié)(示例見(jiàn)第 4.6 節(jié)),這與其它語(yǔ)言如 C++、Java 或者 Python 不同(Java 始終使用 2 個(gè)字節(jié))。Go 這樣做的好處是不僅減少了內(nèi)存和硬盤空間占用,同時(shí)也不用像其它語(yǔ)言那樣需要對(duì)使用 UTF-8 字符集的文本進(jìn)行編碼和解碼。

字符串是一種值類型,且值不可變,即創(chuàng)建某個(gè)文本后你無(wú)法再次修改這個(gè)文本的內(nèi)容;更深入地講,字符串是字節(jié)的定長(zhǎng)數(shù)組。

Go 支持以下 2 種形式的字面值:

  • 解釋字符串:

    該類字符串使用雙引號(hào)括起來(lái),其中的相關(guān)的轉(zhuǎn)義字符將被替換,這些轉(zhuǎn)義字符包括:

    • \n:換行符
    • \r:回車符
    • \t:tab 鍵
    • \u\U:Unicode 字符
    • \\:反斜杠自身
  • 非解釋字符串:

    該類字符串使用反引號(hào)括起來(lái),支持換行,例如:

      `This is a raw string \n` 中的 `\n\` 會(huì)被原樣輸出。

和 C/C++不一樣,Go 中的字符串是根據(jù)長(zhǎng)度限定,而非特殊字符\0。

string 類型的零值為長(zhǎng)度為零的字符串,即空字符串 ""。

一般的比較運(yùn)算符(==!=、<、<=、>=>)通過(guò)在內(nèi)存中按字節(jié)比較來(lái)實(shí)現(xiàn)字符串的對(duì)比。你可以通過(guò)函數(shù) len() 來(lái)獲取字符串所占的字節(jié)長(zhǎng)度,例如:len(str)。

字符串的內(nèi)容(純字節(jié))可以通過(guò)標(biāo)準(zhǔn)索引法來(lái)獲取,在中括號(hào) [] 內(nèi)寫入索引,索引從 0 開始計(jì)數(shù):

  • 字符串 str 的第 1 個(gè)字節(jié):str[0]
  • 第 i 個(gè)字節(jié):str[i - 1]
  • 最后 1 個(gè)字節(jié):str[len(str)-1]

需要注意的是,這種轉(zhuǎn)換方案只對(duì)純 ASCII 碼的字符串有效。

注意事項(xiàng) 獲取字符串中某個(gè)字節(jié)的地址的行為是非法的,例如:&str[i]。

字符串拼接符 +

兩個(gè)字符串 s1s2 可以通過(guò) s := s1 + s2 拼接在一起。

s2 追加在 s1 尾部并生成一個(gè)新的字符串 s。

你可以通過(guò)以下方式來(lái)對(duì)代碼中多行的字符串進(jìn)行拼接:

str := "Beginning of the string " +
    "second part of the string"

由于編譯器行尾自動(dòng)補(bǔ)全分號(hào)的緣故,加號(hào) + 必須放在第一行。

拼接的簡(jiǎn)寫形式 += 也可以用于字符串:

s := "hel" + "lo,"
s += "world!"
fmt.Println(s) //輸出 “hello, world!”

在循環(huán)中使用加號(hào) + 拼接字符串并不是最高效的做法,更好的辦法是使用函數(shù) strings.Join()(第 4.7.10 節(jié)),有沒(méi)有更好地辦法了?有!使用字節(jié)緩沖(bytes.Buffer)拼接更加給力(第 7.2.6 節(jié))!

在第 7 章,我們會(huì)講到通過(guò)將字符串看作是字節(jié)(byte)的切片(slice)來(lái)實(shí)現(xiàn)對(duì)其標(biāo)準(zhǔn)索引法的操作。會(huì)在第 5.4.1 節(jié)中講到的 for 循環(huán)只會(huì)根據(jù)索引返回字符串中的純字節(jié),而在第 5.4.4 節(jié)(以及第 7.6.1 節(jié)的示例)將會(huì)展示如何使用 for-range 循環(huán)來(lái)實(shí)現(xiàn)對(duì) Unicode 字符串的迭代操作。在下一節(jié),我們會(huì)學(xué)習(xí)到許多有關(guān)字符串操作的函數(shù)和方法,同時(shí) fmt 包中的 fmt.Sprint(x) 也可以格式化生成并返回你所需要的字符串(第 4.4.3 節(jié))。

練習(xí) 4.6 count_characters.go

創(chuàng)建一個(gè)用于統(tǒng)計(jì)字節(jié)和字符(rune)的程序,并對(duì)字符串 asSASA ddd dsjkdsjs dk 進(jìn)行分析,然后再分析 asSASA ddd dsjkdsjsこん dk,最后解釋兩者不同的原因(提示:使用 unicode/utf8 包)。

鏈接