您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Go语言

Golang 中的字符串:常见错误和优秀实践

时间:2023-10-24 16:17:55  来源:  作者:爱发白日梦的后端

在这篇文章中,我们将讨论 Golang 中的字符串,并查看一些不同的场景,以避免常见错误。让我们深入探讨!

1. 字符串是否可以为 nil?

我们已经对 Golang 中的字符串有了基本的了解,但我们可以从 Golang 字符串不能为 nil 开始,除非您使用指向字符串的指针。

如下代码所示,当我们创建一个字符串变量时,默认值必须是空的""。如果我们用 nil 值初始化字符串变量,我们将面临在变量声明中不能使用 nil 作为字符串值的错误。例如:

func mAIn() {
 var s string
 s = nil // Cannot use 'nil' as the type string
 fmt.Println(s)
}

编译器会提示我们不能使用 nil 赋予 string 类型。因此,我们可以只是定义变量,或者使用""作为默认值:

func main() {
 var s string
 var ss = ""
 fmt.Println(s, ss)
}

如果我们坚持在字符串类型变量中使用 nil 值,则应使用指针,如下所示:

func main() {
 var s *string
 fmt.Println(s)
}

这个时候输出则为:

<nil>

但是,我们必须谨慎使用这种方法。每次要为变量赋值时,我们都必须编写更多的代码,而且在赋新值之前还要检查是否有零值或前一个值。

func main() {
 var s *string
 tmp := "hello"
 s = &tmp
 fmt.Printf("address: %+v, value: %s", s, *s)
}

这个时候打印出来 s 的地址以及所指向的值:

address: 0xc00008a030, value: hello

2. 字符串是不可变的

Golang 中的字符串是不可变的,这意味着我们不能更改每个字符的值。例如:

func main() {
 tmp := "hello"
 tmp[0] = 'J'
 fmt.Println(tmp)
}

上述代码会导致编译时错误,因为无法赋值给 tmp[0]

更改字符串中单个字符的常见错误如下:

func main() {
 tmp := "hello"
 tbs := []byte(tmp)
 tbs[0] = 'J'
 fmt.Println(string(tbs))

 chi := "你好"
 chiTBS := []byte(chi)
 chiTBS[0] = 'J'
 fmt.Println(string(chiTBS))
}

输出为:

Jello
J��好

虽然第一个输出显示的结果符合我们的预期,但这并不是更改某个字符的正确方法。

这是因为我们打算修改的单个部分可能存储在多个字节中,即使你想将变量转换为符文类型并更改你想要的部分,我也不得不说,这是不可能做到的,因为它可能被放置在多个符文中,我们需要谨慎行事!

3. 字符串是字节数组

在 Golang 中,字符串由字节(字节的片段)组成,某些字符需要存储在多个字节中,例如:"♥"。

因此,当需要确定一个字符串类型变量的长度时,我们必须谨慎编码。例如

func main() {
 tmp := "¥"
 fmt.Println("bytes: ", len(tmp))
 fmt.Println("runes: ", utf8.RuneCountInString(tmp))
}

len 函数返回的是字符串的字节数,而不是字符数。当我们需要找出字符串的符文数时,可以使用 uft8.RuneCountIntString() 函数。

另一个常见的误解是使用 uft8.RuneCountIntString() 来确定字符数,但这并不是在任何情况下都正确,因为一个字符串变量可能跨越多个符文。请看这个例子:

func main() {
 tmp := "❤️"
 fmt.Println("bytes: ", len(tmp))
 fmt.Println("runes: ", utf8.RuneCountInString(tmp))
}

输出为:

bytes:  6
runes:  2

4. 字符串索引和forrange

在 Golang 中,使用索引检索字符串的单个部分将为我们提供字符的 uint 值,并且只能检索第一个字节。但在字符串变量的 for 循环中,我们可以访问每个字符的符值:

func main() {
 tmp := "❤¥%……&*"
 fmt.Printf("char at 0 index, has type %T and value is %+vn", tmp[0], tmp[0])

 for _, t := range tmp {
  fmt.Printf("value is %+v type is %Tn", t, t)
 }
}

输出:

char at 0 index, has type uint8 and value is 226
value is 10084 type is int32
value is 65509 type is int32
value is 37 type is int32
value is 8230 type is int32
value is 8230 type is int32
value is 38 type is int32
value is 42 type is int32

在对字符串进行迭代时,还要注意变量中可能存在的非 UTF8 字符,如果 Golang 无法将其理解为 UTF8,则会使用 unicode 替换而非实际值。

5. 字符串平等

在 Golang 中,我们总是可以使用 == 来检查简单的字符串是否相等,但如果我们的变量存在隐藏点,则应在比较两个字符串变量之前使用 unicode 规范包将其规范化:

func main() {
 cafe1 := "Café"
 cafe2 := "Cafeu0301"

 normalizeCafe1 := norm.NFC.String(cafe1)
 normalizeCafe2 := norm.NFC.String(cafe2)
 fmt.Println(cafe1 == cafe2)
 fmt.Println(normalizeCafe1 == normalizeCafe2)
}

6. 高效字符串构建

使用“+”连接大量字符串的效率可能非常低。使用 strings.Builder 是高效构建字符串的最佳方法之一:

func main() {
 sb := strings.Builder{}
 for i := 0; i < 1000; i++ {
  sb.WriteString("hello ")
 }
 result := sb.String()
 fmt.Println(result)
}

与传统的 + 连接方法相比,这种方法速度更快,内存消耗更少,而且可以避免创建不必要的中间字符串。我们还可以使用 bytes.Buffer 软件包来实现这一目标。

总结

  • 字符串的默认值是""
  • len 和 RuneCountIntString 函数具有不同的行为
  • 我们应该小心 for 循环和字符串
  • 字符串相等是我们需要更精确的地方


Tags:Golang   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
慢聊Golang协程池Ants实现原理
大家都知道goroutine 是 Go语言中的轻量级线程实现,由 Go 运行时(runtime)管理,Go 程序会智能地将 goroutine 中的任务合理地分配给每个 CPU。创建一个goroutine大小大概在2k左...【详细内容】
2023-12-27  Search: Golang  点击:(94)  评论:(0)  加入收藏
基于Go-Kit的Golang整洁架构实践
简介Go是整洁架构(Clean Architecture)的完美选择。整洁架构本身只是一种方法,并没有告诉我们如何构建源代码,在尝试用新语言实现时,认识到这点非常重要。自从我有了使用Ruby o...【详细内容】
2023-12-25  Search: Golang  点击:(154)  评论:(0)  加入收藏
Golang清晰代码指南
发挥易读和易维护软件的好处 - 第一部分嗨,开发者们,清晰的代码是指编写易于阅读、理解和维护的软件代码。它是遵循一组原则和实践,优先考虑清晰性、简单性和一致性的代码。清...【详细内容】
2023-12-18  Search: Golang  点击:(128)  评论:(0)  加入收藏
如何优雅的组织Golang项目结构
一个Go项目的结构设计始终遵循Go语言的简洁高效理念。一个合理和良好的布局可以提高代码的可读性,简化依赖管理,并优化编译过程。像cmd、internal和docs这样的目录是标准Go项...【详细内容】
2023-12-06  Search: Golang  点击:(169)  评论:(0)  加入收藏
从 Discord 的做法中学习 — 使用 Golang 进行请求合并
正如你可能之前看到的,Discord去年发布了一篇有价值的文章,讨论了他们成功存储了数万亿条消息。虽然有很多关于这篇文章的YouTube视频和文章,但我认为这篇文章中一个名为“数据...【详细内容】
2023-11-24  Search: Golang  点击:(257)  评论:(0)  加入收藏
使用Golang进行自动化的20个库
Golang,也被称为Go,是一种静态类型的编译型编程语言,由Robert Griesemer,Rob Pike和Ken Thompson在Google设计。它在2009年推出,旨在解决其他编程语言在并发编程、垃圾回收和代码...【详细内容】
2023-11-23  Search: Golang  点击:(204)  评论:(0)  加入收藏
Golang 中的 Bytes 包详解之 Bytes.Buffer
上篇文章详细讲解了一次性密码 OTP 相关的知识,基于时间的一次性密码 TOTP 是 OTP 的一种实现方式。这种方法的优点是不依赖网络,因此即使在没有网络的情况下,用户也可以生成密...【详细内容】
2023-11-07  Search: Golang  点击:(259)  评论:(0)  加入收藏
聊聊Golang饱受争议的Error
一、error是什么?在C中,返回错误通过errno.h中的错误代码来表示,比如0代表No error,也就是没有错误;2代表No such file or directory,也就是找不到指定路径的文件或文件夹;5代表Inp...【详细内容】
2023-11-06  Search: Golang  点击:(254)  评论:(0)  加入收藏
使用示例和应用程序全面了解高效数据管理的Golang MySQL数据库
Golang,也被称为Go,已经成为构建强大高性能应用程序的首选语言。在处理MySQL数据库时,Golang提供了一系列强大的库,简化了数据库交互并提高了效率。在本文中,我们将深入探讨一些...【详细内容】
2023-10-29  Search: Golang  点击:(307)  评论:(0)  加入收藏
Golang中的强大Web框架
揭示Fiber在Go Web开发中的特点和优势在不断发展的Web开发领域中,选择正确的框架可以极大地影响项目的效率和成功。介绍一下Fiber,这是一款令人印象深刻的Golang(Go语言)Web框架...【详细内容】
2023-10-26  Search: Golang  点击:(258)  评论:(0)  加入收藏
▌简易百科推荐
宝藏级Go语言开源项目——教你自己动手开发互联网搜索引擎
DIYSearchEngine 是一个能够高速采集海量互联网数据的开源搜索引擎,采用 Go 语言开发。Github 地址:https://github.com/johnlui/DIYSearchEngine运行方法首先,给自己准备一杯...【详细内容】
2024-03-12  OSC开源社区    Tags:Go语言   点击:(18)  评论:(0)  加入收藏
Go Gin框架实现优雅地重启和停止
在Web应用程序中,有时候我们需要重启或停止服务器,无论是因为更新代码还是进行例行维护。在这种情景下,我们需要保证应用程序的可用性和数据的一致性。这就需要优雅地关闭和重...【详细内容】
2024-01-30  源自开发者  微信公众号  Tags:Go   点击:(67)  评论:(0)  加入收藏
如何让Go程序以后台进程或daemon方式运行
本文探讨了如何通过Go代码实现在后台运行的程序。最近我用Go语言开发了一个WebSocket服务,我希望它能在后台运行,并在异常退出时自动重新启动。我的整体思路是将程序转为后台...【详细内容】
2024-01-26  Go语言圈  微信公众号  Tags:Go程序   点击:(60)  评论:(0)  加入收藏
深入Go底层原理,重写Redis中间件实战
Go语言以其简洁、高效和并发性能而闻名,深入了解其底层原理可以帮助我们更好地利用其优势。在本文中,我们将探讨如何深入Go底层原理,以及如何利用这些知识重新实现一个简单的Re...【详细内容】
2024-01-25  547蓝色星球    Tags:Go   点击:(66)  评论:(0)  加入收藏
Go 内存优化与垃圾收集
Go提供了自动化的内存管理机制,但在某些情况下需要更精细的微调从而避免发生OOM错误。本文将讨论Go的垃圾收集器、应用程序内存优化以及如何防止OOM(Out-Of-Memory)错误。Go...【详细内容】
2024-01-15  DeepNoMind  微信公众号  Tags:Go   点击:(61)  评论:(0)  加入收藏
Go函数指针是如何让你的程序变慢的?
导读Go 语言的常规优化手段无需赘述,相信大家也能找到大量的经典教程。但基于 Go 的函数值问题,业界还没有太多深度讨论的内容分享。本文作者根据自己对 Go 代码的使用与调优...【详细内容】
2024-01-15  腾讯云开发者  微信公众号  Tags:Go函数   点击:(86)  评论:(0)  加入收藏
Go编程中调用外部命令的几种场景
在很多场合, 使用Go语言需要调用外部命令来完成一些特定的任务, 例如: 使用Go语言调用Linux命令来获取执行的结果,又或者调用第三方程序执行来完成额外的任务。在go的标准库...【详细内容】
2024-01-09  suntiger    Tags:Go编程   点击:(101)  评论:(0)  加入收藏
Go 语言不支持并发读写 Map,为什么?
Go语言的map类型不支持并发读写的主要原因是并发读写会导致数据竞态(data race),这意味着多个 goroutine 可能同时访问并修改同一个 map,从而引发不确定的结果。在Go语言的设计...【详细内容】
2024-01-05  Go语言圈  微信公众号  Tags:Go 语言   点击:(77)  评论:(0)  加入收藏
Go微服务入门到容器化实践
Go微服务入门到容器化实践Go 是一门高效、现代化、快速增长的编程语言,非常适合构建 Web 应用程序。而 Docker 是一种轻量级的容器化技术,能够使得您的应用程序在任何地方运行...【详细内容】
2024-01-01  大雷家吃饭    Tags:Go微服务   点击:(62)  评论:(0)  加入收藏
你是否想知道如何应对高并发?Go语言为你提供了答案!
并发编程是当前软件领域中不可忽视的一个关键概念。随着CPU等硬件的不断发展,我们都渴望让我们的程序运行速度更快、更快。而Go语言在语言层面天生支持并发,充分利用现代CPU的...【详细内容】
2023-12-29  灵墨AI探索室  微信公众号  Tags:Go语言   点击:(107)  评论:(0)  加入收藏
站内最新
站内热门
站内头条