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

如果你从 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)
}

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

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • mongodb处理中文索引与查找字符串详解

    参考文献 首先自打3.2版本之后,就开始支持中文索引了,支持的所有的语言参考这里: https://docs.mongodb.com/manual/reference/text-search-languages/ 然后,对于要支持索引的表需要建议text index,如何建立参考这里: https://docs.mongodb.com/manual/core/index-text/ 在建好索引text之后,如果检索参考: https://docs.mongodb.com/manual/refer

  • Go语言中的字符串处理方法示例详解

    1 概述 字符串,string,一串固定长度的字符连接起来的字符集合.Go语言的字符串是使用UTF-8编码的.UTF-8是Unicode的实现方式之一. Go语言原生支持字符串.使用双引号("")或反引号(``)定义. 双引号:"", 用于单行字符串. 反引号:``,用于定义多行字符串,内部会原样解析. 示例: // 单行 "心有猛虎,细嗅蔷薇" // 多行 ` 大风歌 大风起兮云飞扬. 威加海内兮归故乡. 安得猛士兮守四方! ` 字符串支持转义

  • Go语言常用字符串处理方法实例汇总

    本文实例汇总了Go语言常用字符串处理方法.分享给大家供大家参考.具体如下: 复制代码 代码如下: package main import (     "fmt"     "strings"     //"unicode/utf8" ) func main() {     fmt.Println("查找子串是否在指定的字符串中")     fmt.Println(" Contains 函数的用法")    

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

    如果你从 Ruby 或者 Python 转型到 Go,将会有很多语言差异需要学习,其中很多问题都是围绕处理 string 类型. 下面是一些字符串的技巧,这些技巧解决了我在使用 Golang 的最初几周中遇到的问题. 1. 多行字符串 在 Go 中创建多行字符串非常容易.只需要在你声明或赋值时使用 (``) . str := `This is a multiline string.` 注意 - 任何你在字符串中的缩进都将被保留在最终结果. str := `This string will hav

  • 分享8个Laravel模型时间戳使用技巧小结

    默认情况下,Laravel Eloquent 模型默认数据表有 created_at 和 updated_at 两个字段.当然,我们可以做很多自定义配置,实现很多有趣的功能.下面举例说明. 1. 禁用时间戳 如果数据表没有这两个字段,保存数据时 Model::create($arrayOfValues); -- 会看到 SQL error.Laravel 在自动填充 created_at / updated_at 的时候,无法找到这两个字段. 禁用自动填充时间戳,只需要在 Eloquent Mo

  • PHP入门教程之字符串处理技巧总结(转换,过滤,解析,查找,截取,替换等)

    本文实例总结了PHP字符串处理技巧.分享给大家供大家参考,具体如下: Demo1.php <?php //源代码是文本形式,页面显示是 web 形式 $str = ' PHP '; //清理一下两边的空格 ltrim 只清理左,rtrim只清理右边 echo ltrim($str); echo '<br/>'; echo rtrim($str); echo '<br/>'; //两边都清理 echo trim($str); //echo chop($str); ?> D

  • 分享介绍Python的9个实用技巧

    本文会介绍一些Python大神用的贼溜的技巧,让一探究竟吧!欢迎收藏学习,喜欢点赞支持,欢迎畅聊. 整理字符串输入 整理用户输入的问题在编程过程中很常见.有更好的方法来解决: user_input = "This string has some whitespaces... " character_map = { ord( ) : , ord( ) : , ord( ) : None } user_input.translate(character_map) # This string

  • 分享9个Vue的巧妙冷技巧

    目录 前言 1. 巧用$attrs和$listeners 2. 巧用$props 3. 妙用函数式组件 4. 妙用 Vue.config.devtools 5. 妙用 methods 6. 妙用 watch 的数组格式 7. 妙用$options 8. 妙用 v-pre,v-once v-pre v-once 9. 妙用 hook 事件 前言 写了两年的Vue,期间学习到好几个提高开发效率和性能的技巧,现在把这些技巧用文章的形式总结下来. 1. 巧用$attrs和$listeners $attr

  • 分享一些非常实用的Python小技巧

    目录 1.唯一性 2.变位词(相同字母异序词) 3.内存 4.字节大小 5.打印N次字符串 6.首字母大写 7.列表细分 8.压缩 9.计数 10.链式比较 11.逗号分隔 12.元音计数 13.首字母小写 14.展开列表 15.寻找差异 16.输出差异 17.链式函数调用 18. 19.将两个列表转换为字库 20.出现频率最高的元素 21.回文(正反读有一样的字符串) 22.不用if-else语句的计算器 23.随机排序 24.展开列表 1.唯一性 以下方法可以检查给定列表是否有重复的地方,可

  • 分享五个PHP7性能优化提升技巧

    PHP7已经发布了, 作为PHP10年来最大的版本升级, 最大的性能升级, PHP7在多放的测试中都表现出很明显的性能提升, 然而, 为了让它能发挥出最大的性能, 我还是有几件事想提醒下. 1. Opcache 记得启用Zend Opcache, 因为PHP7即使不启用Opcache速度也比PHP-5.6启用了Opcache快, 所以之前测试时期就发生了有人一直没有启用Opcache的事情. 启用Opcache非常简单, 在php.ini配置文件中加入: zend_extension=opcac

  • 分享5个实用的vs调试技巧

    并行堆栈 作用简介: 我们可以通过调用堆栈窗口查看当前线程的调用栈,局限是只能查看某个线程的调用栈,要想查看每个线程的调用栈得切来切去的,太麻烦.如果我们想同时查看多个线程的调用情况,我们可以使用并行堆栈窗口.顾名思义,并行堆栈窗口可以同时查看多个线程的调用栈.如果程序中的某个线程死循环了,我们想确定是哪个,这时候可以中断到 vs 中,然后打开并行堆栈窗口进行查看,基本上可以很快定位到出问题的代码. 打开方式: 调试的时候,通过 调试 -> 窗口 -> 并行堆栈 即可打开.在 vs2013 中

  • 分享几个JavaScript运算符的使用技巧

    ECMAScript发展进程中,会有很多功能的更新,比如销毁,箭头功能,模块,它们极大的改变JavaScript编写方式,可能有些人喜欢,有些人不喜欢,但像每个新功能一样,我们最终会习惯它们.新版本的ECMAScript引入了三个新的逻辑赋值运算符:空运算符,AND和OR运算符,这些运算符的出现,也是希望让我们的代码更干净简洁,下面分享几个优雅的JavaScript运算符使用技巧 一.可选链接运算符[?.] 可选链接运算符(Optional Chaining Operator) 处于ES2020

  • 分享9个好用的Python技巧

    目录 1.引言 2.Trick 1 3.Trick 2 4.Trick3 5.Trick4 6.Trick5 7.Trick6 8.Trick7 9.Trick8 10.Trick9 11.总结 1.引言 本文是Python生态系统中一些有用技巧的分享.大多数技巧只是使用标准库中的包,但其他一些技巧会涉及一些第三方包. 在开始阅读本文内容之前,我们首先来回顾一下Python中的Iterables的概念. 根据Python标准文档,Iterable的概念如下: 一种能够一次返回一个成员的对象. i

随机推荐