分享 6 个 Go 处理字符串的技巧

Golang

如果你从 Ruby 或者 Python 转型到 Go,将会有很多语言差异需要学习,其中很多问题都是围绕处理 string 类型。
下面是一些字符串的技巧,这些技巧解决了我在使用Golang的最初几周中遇到的问题。

1.多行字符串

在 Go 中创建多行字符串非常容易。只需要在你声明或赋值时使用 (``) 。

str := `This is a
multiline
string.`

在线练习 → https://play.golang.org/p/mpIQuNhC1kr

注意 - 任何你在字符串中的缩进都将被保留在最终结果。

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

在线练习 → https://play.golang.org/p/mpIQuNhC1kr

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

在线练习 → https://play.golang.org/p/mtDENayW8dU

如果你提前准备好所有字符串,你也可以通过 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-"
}

在线练习 → https://play.golang.org/p/-nMvx3hKhwR

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

在线练习 → https://play.golang.org/p/_q0n1NIgPZQ

你还可以使用fmt.Sprintf函数将几乎所有数据类型转换为字符串,但通常应保留在这样的实例上,如正在创建的字符串包含嵌入数据,而非在期望将单个整数转换为字符串时用。

package main

import "fmt"

func main() {
    i := 123
    t := fmt.Sprintf("We are currently processing ticket number %d.", i)
    fmt.Println(t)
}

在线练习 → https://play.golang.org/p/DSJkfat7iAo

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

在线练习 → https://play.golang.org/p/ocwA3yKS6he

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

在线练习 → https://play.golang.org/p/amPjDXejZJl

虽然 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)
}

在线练习 → https://play.golang.org/p/D2lzr7BfAdX

以上就是Go 语言字符串使用过程中的一些小技巧,希望能帮到你。如果你需要更多 Go 相关的实践,可以查阅我发表的其他相关教程。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://www.calhoun.io/6-tips-for-using-...

译文地址:https://learnku.com/go/t/36734

本帖已被设为精华帖!
本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!