分享6个Go处理字符串的技巧小结
作者:zx 发布时间:2024-01-30 17:39:07
如果你从 Ruby 或者 Python 转型到 Go,将会有很多语言差异需要学习,其中很多问题都是围绕处理 string 类型。
下面是一些字符串的技巧,这些技巧解决了我在使用 Golang 的最初几周中遇到的问题。
1. 多行字符串
在 Go 中创建多行字符串非常容易。只需要在你声明或赋值时使用 (``) 。
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)
}
来源:https://learnku.com/golang/t/36734


猜你喜欢
- 本文实例讲述了Python基于lxml模块解析html获取页面内所有叶子节点xpath路径功能。分享给大家供大家参考,具体如下:因为需要使用
- 目录背景引入虚拟文件例子文档Typescript支持总结背景在新项目升级vue3以后,自然而然的就把vue-cli&webpack更
- Logistic Regression Classifier逻辑回归主要思想就是用最大似然概率方法构建出方程,为最大化方程,利用牛顿梯度上升
- 上一篇:微软建议的ASP性能优化28条守则(7)技巧 22:尽可能使用 Server.Transfer 代替 Response.Redire
- 有时候,我们需要将TensorFlow的模型导出为单个文件(同时包含模型架构定义与权重),方便在其他地方使用(如在c++中部署网络)。利用t
- 大家都知道索引对于数据访问的性能有非常关键的作用,都知道索引可以提高数据访问效率。为什么索引能提高数据访问性能?他会不会有“副作用”?是不是
- 这篇文章主要介绍了Python函数参数类型及排序原理总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的
- 今早打开 腾讯ISD的博客 ,看到一篇新的文章,《迷你屋视觉规范简介》,赶紧看了来学习。不过给我抓到问题咯,臭鱼不介意我在这说下吧:这套规范
- 决定数据类型的第一步是定义所存数数据的分类: 数值型, 字符串型还是临时型等;除了一些特别的并不是那么直观的外, 这通常是很直观的。接下来是
- 上一篇我们讲过Cookie相关的知识,了解到Cookie是为了交互式web而诞生的,它主要用于以下三个方面:会话状态管理(如用户登录状态、购
- 本文给大家分享的是查看MySQL连接的root密码的方法,下面话不多说来来看正文:1.首先我们进到MySQL的bin目录下➜ cd /usr
- 一、匿名块和命名块◆PL/SQL块分为良好总:命名块和匿名块。◆匿名块:以declare或begin开始,每次执行匿名块都要通过客户端工具将
- 长话短说,今天介绍实现此功能的一个方法,需要了解的朋友可以参考下:一、JS 重载页面,本地刷新,返回上一页 代码如下:<a href=
- 见下表:序号保留字序号保留字序号保留字1ADD80ESCAPE159OR2ABSOLUTE81EXCEPT160ORDER3ACTION82
- 简介:图像二值化就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。普通图像二值化代码如下:impor
- 前言如果我们和面试官聊到事务的问题,怎么回答呢?先说下事务是什么,因为我们业务是比较复杂的,不可能一个sql就能解决的,涉及多个sql就组成
- 一、数据容器:list(列表)列表内的每一个数据,称之为元素以 [] 作为标识列表内每一个元素之间用, 逗号隔开定义语法:[元素1, 元素2
- Python编写微信小游戏“跳一跳”的运行脚本,分享给大家。更新了微信后发现了一款小游戏跳一跳,但是玩了一下午最高才达到200,每次差点破纪
- 本文实例讲述了基于Python开发chrome插件的方法。分享给大家供大家参考,具体如下:谷歌Chrome插件是使用HTML、JavaScr
- 今天在启动mysql时出现以下问题:[root@www ~]# mysql -u root -pEnter password: ERROR