溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

golang常用的字符串處理方式

發(fā)布時(shí)間:2020-06-15 17:00:15 來源:億速云 閱讀:283 作者:元一 欄目:編程語言

Go語言概念

Go(又稱Golang)是Google開發(fā)的一種靜態(tài)強(qiáng)類型、編譯型、并發(fā)型,并具有垃圾回收功能的編程語言。

羅伯特·格瑞史莫(Robert Griesemer),羅勃·派克(Rob Pike)及肯·湯普遜(Ken Thompson)于2007年9月開始設(shè)計(jì)Go,稍后Ian Lance Taylor、Russ Cox加入項(xiàng)目。Go是基于Inferno操作系統(tǒng)所開發(fā)的。Go于2009年11月正式宣布推出,成為開放源代碼項(xiàng)目,并在Linux及Mac OS X平臺(tái)上進(jìn)行了實(shí)現(xiàn),后來追加了Windows系統(tǒng)下的實(shí)現(xiàn)。在2016年,Go被軟件評(píng)價(jià)公司TIOBE 選為“TIOBE 2016 年最佳語言”。 目前,Go每半年發(fā)布一個(gè)二級(jí)版本(即從a.x升級(jí)到a.y)。

字符串概念
字符串或串(String)是由數(shù)字、字母、下劃線組成的一串字符。一般記為 s="a1a2···an"(n>=0)。它是編程語言中表示文本的數(shù)據(jù)類型。在程序設(shè)計(jì)中,字符串(string)為符號(hào)或數(shù)值的一個(gè)連續(xù)序列,如符號(hào)串(一串字符)或二進(jìn)制數(shù)字串(一串二進(jìn)制數(shù)字)。

1、多行字符串

str := `This is a
multiline
string.`

注意 - 任何你在字符串中的縮進(jìn)都將被保留在最終結(jié)果。

str := `This string
    will have
    tabs in it`

2. 高效的字符串連接方式

Go 允許你通過 "+" 的方式連接字符串,但這種方式在處理大量字符串連接的場(chǎng)景下將非常低效。使用 bytes.Buffer 連接字符串是一個(gè)更高效的方式,它會(huì)一次性將所有的內(nèi)容連接起來轉(zhuǎn)化成字符串。

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 {
    // 模擬返回一個(gè)隨機(jī)字符串
    return "abc-123-"
}

如果你提前準(zhǔn)備好所有字符串,你也可以通過 strings.Join 的方式實(shí)現(xiàn)。

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 {
    // 模擬返回一個(gè)隨機(jī)字符串
    return "abc-123-"
}

3. 將整型 (或任意數(shù)據(jù)類型) 轉(zhuǎn)為字符串

在大多數(shù)語言中,可輕易地將任意數(shù)據(jù)類型轉(zhuǎn)型為字符串進(jìn)行拼接,或用字符串插入(例如在 ruby 中這樣 "ID=#{id}")。很不幸,如果你嘗試在 Go 中去做這種顯示而易見的操作,比如強(qiáng)制將整形轉(zhuǎn)為字符串,你不會(huì)得到期望的結(jié)果。

i := 123
s := string(i)

你希望 s 的輸出是多少?如果你像大多數(shù)人一樣猜測(cè) "123",那你就大錯(cuò)特錯(cuò)了。相反,你會(huì)得到類似 "E" 的值。這根本不是我們想要的!

相反,您應(yīng)該使用像 [strconv] (https://golang.org/pkg/strconv/) 這樣的包或像 fmt.Sprintf 這樣的函數(shù)。例如,下面是一個(gè)使用 strconv.Itoa 將整數(shù)轉(zhuǎn)換為字符串的示例。

package main
import (
    "fmt"
    "strconv"
)
func main() {
    i := 123
    t := strconv.Itoa(i)
    fmt.Println(t)
}

你還可以使用 fmt.Sprintf 函數(shù)將幾乎所有數(shù)據(jù)類型轉(zhuǎn)換為字符串,但通常應(yīng)保留在這樣的實(shí)例上,如正在創(chuàng)建的字符串包含嵌入數(shù)據(jù),而非在期望將單個(gè)整數(shù)轉(zhuǎn)換為字符串時(shí)用。

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 幾乎相同,只是它沒有將結(jié)果字符串輸出到標(biāo)準(zhǔn)輸出,而是將其作為字符串返回。

限制使用 Sprintf

如前所述,fmt.Sprintf 通常應(yīng)用在創(chuàng)建具有嵌入值的字符串。這有幾個(gè)原因,但最突出的一個(gè)原因是 fmt.Sprintf 不做任何類型檢查,因此在實(shí)際運(yùn)行代碼之前,您不太可能發(fā)現(xiàn)任何錯(cuò)誤。

Sprintf 也比你通常在 strconv 包中使用的大多數(shù)函數(shù)慢,不過如果我說實(shí)話,速度差異是如此之小,一般不值得考慮。

4. 創(chuàng)建隨機(jī)字符串

這并不是一個(gè)真正的「快速技巧」,但我發(fā)現(xiàn)這是一個(gè)經(jīng)常被問到的問題。

如何在 Go 中創(chuàng)建隨機(jī)的字符串?

聽上去很簡(jiǎn)單。許多語言,比如 Ruby 和 Python,都提供了一些幫助程序,使隨機(jī)字符串的生成變得非常簡(jiǎn)單,所以 Go 肯定有這樣一個(gè)工具,對(duì)吧?答案是錯(cuò)誤的。

Go 選擇只提供創(chuàng)建隨機(jī)字符串的工具,而將細(xì)節(jié)留給開發(fā)人員。雖然一開始可能會(huì)有些困難,但好處是您可以完全決定如何生成字符串。 這意味著您可以指定字符集、如何播種隨機(jī)生成以及任何其他詳細(xì)信息。簡(jiǎn)而言之,你有更多的控制權(quán),但代價(jià)是需要寫一些額外的代碼。

下面是一個(gè)使用 math/rand 包和一組字母數(shù)字字符作為字符集的快速示例。

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 練習(xí)場(chǎng)總是輸出相同的字符串

如果您在 Go 練習(xí)場(chǎng)上多次運(yùn)行這段代碼,您可能會(huì)注意到它總是輸出相同的字符串 - aJFLa7XPH5。

這是因?yàn)?Go 練習(xí)場(chǎng)總是使用相同的時(shí)間,所以當(dāng)我們用 rand.NewSource 方法時(shí)。在當(dāng)前時(shí)間內(nèi)傳遞的那個(gè)值總是相同的,所以我們生成的字符串總是相同的。

對(duì)于您的特定需求,可能有比這個(gè)更優(yōu)的解決方案,但這是一個(gè)很好的起點(diǎn)。如果您正在尋找改進(jìn) / 更改代碼的方法,您可能會(huì)考慮使用 crypto/rand 包來生成隨機(jī)數(shù)據(jù) — 這通常更安全,但最終可能需要更多的工作。

無論您最終使用的是什么,這個(gè)示例都應(yīng)該有助于您入門。 對(duì)于大多數(shù)不涉及密碼和身份驗(yàn)證系統(tǒng)等敏感數(shù)據(jù)的實(shí)際用例,它工作得足夠好。 只是一定要記得你的種子隨機(jī)數(shù)發(fā)生器!這可以通過 rand.Seed 函數(shù)在 math/rand 包中完成,或者創(chuàng)建一個(gè)源代碼。在上面的例子中,我選擇創(chuàng)建一個(gè)源代碼。

5. strings 包、HasPrefix 和自定義代碼

在處理字符串時(shí),想要知道一個(gè)字符串是以一個(gè)特定的字符串開始還是以一個(gè)特定的字符串結(jié)束是非常常見的情況。例如,如果您的 API 鍵都以 sk_ 開頭,那么您可能希望驗(yàn)證 API 請(qǐng)求中提供的所有 API 鍵都以這個(gè)前綴開頭,否則進(jìn)行數(shù)據(jù)庫(kù)查找將浪費(fèi)大量時(shí)間。

對(duì)于那些聽起來像是非常常見的用例的函數(shù),您最好的選擇通常是直接訪問 strings 包并檢查一些可能對(duì)您有幫助的內(nèi)容。在這種情況下,你會(huì)想要使用功能 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 包中有大量有用的公共函數(shù),但值得注意的是,并不總是值得去尋找一個(gè)能滿足您需要的包。如果你有其他語言經(jīng)驗(yàn)正在學(xué)習(xí) Go 語言,一個(gè)常見的錯(cuò)誤是開發(fā)者花太多時(shí)間尋找能夠提供所需功能的包,而他們自己可輕易地編碼實(shí)現(xiàn)這功能。

使用標(biāo)準(zhǔn)庫(kù)肯定有好處(如它們經(jīng)過了徹底的測(cè)試并有很好的文檔記錄)。盡管有這些好處,但如果你發(fā)現(xiàn)自己花了超過幾分鐘的時(shí)間來尋找一個(gè)函數(shù),那么自己編寫它通常也是有益的。在這種情況下,根據(jù)需求自定義(編碼),將很快完成,你將完全了解正在發(fā)生的事情,不會(huì)被奇怪的邊界情況(譯者注如索引越界)措手不及。您也不必?fù)?dān)心其他人維護(hù)代碼。

6. 字符串可以被轉(zhuǎn)換成 byte 切片 (反之亦然)

Go 語言可以將一個(gè)字符串轉(zhuǎn)換成 byte 切片 ([]byte) ,也可以將 byte 切片轉(zhuǎn)換成字符串。轉(zhuǎn)換的過程跟其他任意類型轉(zhuǎn)換的方式一樣簡(jiǎn)單。這種轉(zhuǎn)換方式通常用于為一個(gè)接收 byte 切片參數(shù)的函數(shù)傳遞一個(gè)字符串 以及 為一個(gè)接收字符串參數(shù)的函數(shù)傳遞 byte 切片的場(chǎng)景。

下面是一個(gè)轉(zhuǎn)換的例子:

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 處理字符串的技巧的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注億速云其它相關(guān)文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI