1、多行字串
str := `This is a multiline string.`
注意 - 任何你在字串中的縮排都會保留在最終結果。
str := `This string will have tabs in it`
2. 高效的字串連接方式
Go 允許你透過" " 的方式連接字串,但這種方式在處理大量字串連接的場景下將非常低效。使用 bytes.Buffer 連接字串是一個更有效率的方式,它會一次將所有的內容連接起來轉換成字串。
package main import ( "bytes" "fmt" ) func main() { var b bytes.Buffer for i := 0; i < 1000; i++ { b.WriteString(randString()) } fmt.Println(b.String()) } func randString() string { // 模拟返回一个随机字符串 return "abc-123-" }
如果你事先準備好所有字串,你也可以透過 strings.Join 的方式實作。
package main import ( "fmt" "strings" ) func main() { var strs []string for i := 0; i < 1000; i++ { strs = append(strs, randString()) } fmt.Println(strings.Join(strs, "")) } func randString() string { // 模拟返回一个随机字符串 return "abc-123-" }
3. 將整數(或任意資料型別) 轉為字串
在大多數語言中,可輕易地將任意資料型別轉換為字串進行拼接,或用字串插入(例如在ruby 中這樣"ID=#{id}")。很不幸,如果你嘗試在 Go 中去做這種顯示而易見的操作,例如強制將整形轉為字串,你不會得到期望的結果。
i := 123 s := string(i)
你希望 s 的輸出是多少?如果你像大多數人一樣猜測 "123",那你就大錯特錯了。相反,你會得到類似 "E" 的值。這根本不是我們想要的!
相反,您應該使用像 [strconv] (https://golang.org/pkg/strconv/) 這樣的套件或像 fmt.Sprintf 這樣的函數。例如,下面是一個使用 strconv.Itoa 將整數轉換為字串的範例。
package main import ( "fmt" "strconv" ) func main() { i := 123 t := strconv.Itoa(i) fmt.Println(t) }
你也可以使用fmt.Sprintf 函數將幾乎所有數據類型轉換為字串,但通常應保留在這樣的實例上,如正在創建的字串包含嵌入數據,而不是在期望將單一整數轉換為字串時用。
package main import "fmt" func main() { i := 123 t := fmt.Sprintf("We are currently processing ticket number %d.", i) fmt.Println(t) }
Sprintf 的操作與 fmt.Printf 幾乎相同,只是它沒有將結果字串輸出到標準輸出,而是將其作為字串傳回。
限制使用 Sprintf
如前所述,fmt.Sprintf 通常會套用在建立具有嵌入值的字串。這有幾個原因,但最突出的一個原因是 fmt.Sprintf 不做任何類型檢查,因此在實際執行程式碼之前,您不太可能發現任何錯誤。
Sprintf 也比你通常在 strconv 套件中使用的大多數函數慢,不過如果我說實話,速度差異是如此之小,一般不值得考慮。
4. 創建隨機字串
這並不是一個真正的「快速技巧」,但我發現這是一個經常被問到的問題。
如何在 Go 中建立隨機的字串?
聽起來很簡單。許多語言,例如 Ruby 和 Python,都提供了一些幫助程序,使隨機字串的生成變得非常簡單,所以 Go 肯定有這樣一個工具,對吧?答案是錯的。
Go 選擇只提供建立隨機字串的工具,而將細節留給開發人員。雖然一開始可能會有些困難,但好處是您可以完全決定如何產生字串。這意味著您可以指定字元集、如何播種隨機生成以及任何其他詳細資訊。簡而言之,你有更多的控制權,但代價是需要寫一些額外的程式碼。
下面是一個使用 math/rand 套件和一組字母數字字元作為字元集的快速範例。
package main import ( "fmt" "math/rand" "time" ) func main() { fmt.Println(RandString(10)) } var source = rand.NewSource(time.Now().UnixNano()) const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" func RandString(length int) string { b := make([]byte, length) for i := range b { b[i] = charset[source.Int63()%int64(len(charset))] } return string(b) }
Go 練習場總是輸出相同的字串
如果您在Go 練習場上多次執行這段程式碼,您可能會注意到它總是輸出相同的字串- aJFLa7XPH5。
這是因為 Go 練習場總是使用相同的時間,所以當我們使用 rand.NewSource 方法。在當前時間內傳遞的那個值總是相同的,所以我們產生的字串總是相同的。
對於您的特定需求,可能有比這個更優的解決方案,但這是一個很好的起點。如果您正在尋找改進 / 更改程式碼的方法,您可能會考慮使用 crypto/rand 套件來產生隨機資料 — 這通常更安全,但最終可能需要更多的工作。
無論您最終使用的是什麼,這個範例都應該有助於您入門。對於大多數不涉及密碼和身份驗證系統等敏感資料的實際用例,它工作得足夠好。只是一定要記得你的種子隨機數字產生器!這可以透過 rand.Seed 函數在 math/rand 套件中完成,或是建立一個原始碼。在上面的例子中,我選擇建立一個原始碼。
5. strings 套件、HasPrefix 和自訂程式碼
在處理字串時,想要知道一個字串是以一個特定的字串開始還是以一個特定的字串結束是非常常見的情況。例如,如果您的 API 鍵都以 sk_ 開頭,那麼您可能想要驗證 API 請求中提供的所有 API 鍵都以這個前綴開頭,否則進行資料庫查找將浪費大量時間。
對於那些聽起來像是非常常見的用例的函數,您最好的選擇通常是直接存取 strings 套件並檢查一些可能對您有幫助的內容。在這種情況下,你會想要使用函數 HasPrefix(str, prefix) 和 strings.HasSuffix(str, prefix)。你可以在下面看到他們的用法。
package main import ( "fmt" "strings" ) func main() { fmt.Println(strings.HasPrefix("something", "some")) fmt.Println(strings.HasSuffix("something", "thing")) }
虽然 strings 包中有大量有用的公共函数,但值得注意的是,并不总是值得去寻找一个能满足您需要的包。如果你有其他语言经验正在学习 Go 语言,一个常见的错误是开发者花太多时间寻找能够提供所需功能的包,而他们自己可轻易地编码实现这功能。
使用标准库肯定有好处(如它们经过了彻底的测试并有很好的文档记录)。尽管有这些好处,但如果你发现自己花了超过几分钟的时间来寻找一个函数,那么自己编写它通常也是有益的。在这种情况下,根据需求自定义(编码),将很快完成,你将完全了解正在发生的事情,不会被奇怪的边界情况(译者注如索引越界)措手不及。您也不必担心其他人维护代码。
6. 字符串可以被转换成 byte 切片 (反之亦然)
Go 语言可以将一个字符串转换成 byte 切片 ([]byte) ,也可以将 byte 切片转换成字符串。转换的过程跟其他任意类型转换的方式一样简单。这种转换方式通常用于为一个接收 byte 切片参数的函数传递一个字符串 以及 为一个接收字符串参数的函数传递 byte 切片的场景。
下面是一个转换的例子:
package main import "fmt" func main() { var s string = "this is a string" fmt.Println(s) var b []byte b = []byte(s) fmt.Println(b) for i := range b { fmt.Println(string(b[i])) } s = string(b) fmt.Println(s) }
以上就是 Go 语言字符串使用过程中的一些小技巧,希望能帮到你。如果你需要更多 Go 相关的实践,可以查阅我发表的其他相关教程。
推荐教程:《Go教程》
以上是常見的 Go 處理字串的技巧的詳細內容。更多資訊請關注PHP中文網其他相關文章!