Golang 中的字符串:常见错误和最佳实践

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

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

我们已经对 Golang 中的字符串有了基本的了解,但我们可以从 Golang 字符串不能为 nil 开始,除非您使用指向字符串的指针。
如下代码所示,当我们创建一个字符串变量时,默认值必须是空的""。如果我们用 nil 值初始化字符串变量,我们将面临在变量声明中不能使用 nil 作为字符串值的错误。例如:

func main() {var s strings = nil // Cannot use 'nil' as the type stringfmt.Println(s)
}

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

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

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

func main() {var s *stringfmt.Println(s)
}

这个时候输出则为:

<nil>

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

func main() {var s *stringtmp := "hello"s = &tmpfmt.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
  1. 字符串索引和forrange
    在 Golang 中,使用索引检索字符串的单个部分将为我们提供字符的 uint 值,并且只能检索第一个字节。但在字符串变量的 for 循环中,我们可以访问每个字符的符值:
func main() {tmp := "❤¥%……&*"fmt.Printf("char at 0 index, has type %T and value is %+v\n", tmp[0], tmp[0])for _, t := range tmp {fmt.Printf("value is %+v type is %T\n", 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 := "Cafe\u0301"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 循环和字符串
  • 字符串相等是我们需要更精确的地方

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/702499.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

栈和队列笔试题

答案&#xff1a;&#xff08;1&#xff09;seqn[tail]data; tail(tail1)%SEQLEN; &#xff08;2&#xff09;data seqn[head]; head (head1)%SEQLEN; &#xff08;3&#xff09;head tail; &#xff08;4&#xff09;(tail1)%SEQLEN head; (5) while(head!tail) head (h…

JVM内存结构介绍

1.程序计数器&#xff08;Program Counter Register&#xff09; 程序计数器是一块较小的内存空间&#xff0c;它的作用可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里&#xff08;仅是概念模型&#xff0c;各种虚拟机可能会通过一些更高效的方式去实现&…

电商评价分析:NLP信息抽取技术在用户评论中的应用与挖掘

一、引言 在2019年&#xff0c;电子商务的蓬勃发展不仅推动了消费市场的增长&#xff0c;也带来了海量的用户评价数据。这些数据&#xff0c;作为消费者对商品和服务直接反馈的载体&#xff0c;蕴含着巨大的价值。然而&#xff0c;由于其非结构化的特性&#xff0c;这些文本信息…

解决ssh:connect to host github.com port 22: Connection timed out与kex_exchange_identification

一、问题 无法进行clone项目和其他Git操作。执行检测连接命令 ssh -T gitgithub,com报错 ssh:connect to host github.com port 22: Connection timed out 即&#xff1a;连接22端口超时 涉及到的文件&#xff1a; C:\Users\JIACHENGER.ssh\config C:\Users\JIACHENGER.ssh\…

WPF 限制输入只能为英文

WPF 限制输入只能为英文 有时输入只能让用户输入英文&#xff0c;那么如何设置输入只能英文&#xff1f; 方法一&#xff1a;在Xaml页面中直接限制文本输入框输入 <Windowxmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http:…

Python实用技巧:输出列表(list)的倒序/逆序的几种方法

Python实用技巧&#xff1a;输出列表&#xff08;list&#xff09;的倒序/逆序的几种方法 &#x1f4c5;2024年02月25日 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质…

Linux修改shell工具连接端口

nano /etc/ssh/sshd_config 或者 vi /etc/ssh/sshd_config 或者 vim /etc/ssh/sshd_config

gin框架和gorm框架(不断更新......)

Gin怎么做参数校验 在 Gin 框架中&#xff0c;你可以使用 binding 和 validator 包来进行参数校验。 定义请求参数的结构体&#xff1a; type CreateUserRequest struct {Username string json:"username" binding:"required,alphanum,min4,max20"Email…

面试题整理1

文章目录 前言1.socket的过程2.谈谈你对数据库中索引的理解3.现在普通关系数据库用的数据结构是什么类型的数据结构4.索引的优点和缺点5.session、cookie和cache的区别是什么&#xff1f;6.如果有几千个session&#xff0c;怎么提高效率&#xff1f;7.session是存储在什么地方&…

港口人车防撞定位方案

大家好&#xff0c;我是北京华星智控公司小智&#xff0c;今天给大家介绍港口人员定位防撞安全管控方案。 首先说明项目建设背景、目的和面临的挑战&#xff0c;背景介绍&#xff1a; 港口作为货物运输和交换的重要节点&#xff0c;人员和机械设备频繁活动&#xff0c;存在碰撞…

pytorch -- 常见的transform包方法

1. 基础 PIL Image -> Image.open tensor -> ToTensor() [Convert a PIL Image or ndarray to tensor] ndarray -> cv2.imread 2. 常见方法 (1)ToTensor 将PIL/numpy ndarry转化为tensor from PIL import Image from torch.utils.tensorboard import SummaryWrite…

8.7 OpenGL纹理和采样器:压缩纹理图像

压缩纹理图像 Compressed Texture Images 纹理图像也可以使用已存储在已知压缩图像格式中的图像数据来指定或修改&#xff0c;这些格式包括附录D中定义的格式以及由扩展定义的任何额外格式。 void glCompressedTexImage1D( enum target, int level, enum internalformat, siz…

安装虚拟机出现的一些问题

1、在重新打开软件之后出现闪退 解决&#xff1a;[WSL] 解决nsenter: cannot open /proc/320/ns/time: No such file or directory 问题 小白向-CSDN博客2、重新启动xrdp服务命令 解决&#xff1a; sudo systemctl restart xrdp3、将端口从3389改为3390&#xff0c;因为此前…

统信UOS系统窗口特效设置

原文链接&#xff1a;统信UOS系统设置窗口特效 在今天的技术分享中&#xff0c;我们将探讨如何在统信UOS系统上充分利用窗口特效来美化和提升用户界面的交互体验。统信UOS作为一款注重视觉体验和用户友好性的操作系统&#xff0c;提供了丰富的窗口特效设置&#xff0c;让用户可…

利用Java SPI机制实现可插拔的应用插件

自己搭建了个小博客&#xff0c;本文与这篇文章同步&#xff1a; 利用Java SPI机制实现可插拔的应用插件 什么是spi Java SPI&#xff08;Service Provider Interface&#xff09;机制是 Java 提供的一种用于实现组件化、可插拔式架构的机制。通过 SPI&#xff0c;Java 应用…

js之防抖与节流

定义&#xff1a;多次触发事件后&#xff0c;事件处理函数只执行一次&#xff0c;并且在触发操作结束时执行&#xff0c;一般用于scroll事件 原理&#xff1a;对处理函数进行延时操作&#xff0c;若设定的延时到来之前再次触发事件&#xff0c;则清除上一次的延时操作定时器&am…

从零开始学HCIA之广域网技术03

1、LCP中包含的报文类型 &#xff08;1&#xff09;Configure-Request&#xff08;配置请求&#xff09;&#xff0c;链路层协商过程中发送的第一个报文&#xff0c;该报文表明点对点双方开始进行链路层参数的协商。 &#xff08;2&#xff09; Configure-Ack&#xff08;配置…

详解 CSS 的背景属性

详解 CSS 的背景属性 背景颜色 语法&#xff1a; background-color: [指定颜色]; 注&#xff1a;默认是 transparent (透明) 的&#xff0c;可以通过设置颜色的方式修改 示例代码: 运行效果: 背景图片 语法&#xff1a;background-image: url(...); url 可以是绝对路径 也可…

oracle 设置权限 禁止删除用户

在Oracle中&#xff0c;可以通过修改系统角色来控制用户的操作权限。要禁止删除用户&#xff0c;需要将DROP USER这个特定的系统权限从相应的角色中移除。 下面是一种常见的方法&#xff0c;使用SQL语句进行操作&#xff1a; -- 创建新的角色&#xff0c;并为其分配所有必要的…

小苯的IDE括号问题(CD) -----牛客小白月赛87(双链表)

C题&#xff1a;C-小苯的IDE括号问题&#xff08;easy&#xff09;_牛客小白月赛87 (nowcoder.com) D题&#xff1a; D-小苯的IDE括号问题&#xff08;hard&#xff09;_牛客小白月赛87 (nowcoder.com) C题代码&#xff1a; #include<bits/stdc.h>using namespace std…