Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Go语言中常见100问题-#40 Useless string conversions

Go语言中常见100问题-#40 Useless string conversions

作者头像
数据小冰
发布于 2023-08-17 00:33:53
发布于 2023-08-17 00:33:53
15000
代码可运行
举报
文章被收录于专栏:数据小冰数据小冰
运行总次数:0
代码可运行
无意义的字符串转换

当编码操作的类型既可以是 []byte 又可以是 string时,大多数程序员倾向使用string类型,因为这样可能更方便。但是大多数的 I/O 操作采用的类型是 []byte。例如 io.Readerio.Writerio.ReadAll. 如果拿到的类型是string,但又要使用这些接口意味着需要进行类型转换,strings包提供了相关的转换函数。

下面看一个没有必要进行转换的例子。getBytes函数从入参io.Reader中读取字节流,然后调用sanitize函数,去掉首尾的空白符。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func getBytes(reader io.Reader) ([]byte, error) {
 b, err := io.ReadAll(reader)
 if err != nil {
  return nil, err
 }
 // call sanitize
}

io.ReadAll返回的是字节切片(赋值给b),sanitize函数如何实现呢?一种思路是接收一个string参数返回值也是string,内部调用strings包的TrimSpace处理。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func sanitize(s string) string {
 return strings.TrimSpace(s)
}

回到getBytes函数,拿到的b是[]byte,需要将其转换为string才能调用sanitize,对于返回值,由于sanitize返回的是字符串,但是getBytes返回的是[]byte,所以也需要进行逆向转换。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
return []byte(sanitize(string(b))),nil

看到这里实现存在的问题了吗?我们需要进行额外的转换,将[]byte转为string,返回的时候又要将string转回为[]byte. 每次转换需要分配额外的内存,尽管string的内部也有一个[]byte,但是转换为[]byte需要将string内部[]byte中的内容拷贝新分配的[]byte中,因为字符串string不可变特性。

字符串不可变特性

可以通过一段代码验证字符串的不可变特性,如下所示。字节切片b由字符a、b、c构成,然后通过b创建字符串s, 现在修改切片b中第二位置元素,即从b换成x,然后打印字符串s,观察s是否为axc.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
b := []byte{'a', 'b', 'c'}
s := string(b)
b[1] = 'x'
fmt.Println(s)

实际运行输出的是abc而不是axc,可以验证s和b不是共享同一个切片。

那如何实现 sanitize函数呢?将其入参和返回值类型都改为[]byte类型,这样就不用进行额外转换。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func sanitize(b []byte) []byte {
 return bytes.TrimSpace(b)
}

bytes包也有去除空白符函数TrimSpace,直接调用bytes.TrimSpace,不需要额外转换。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
return sanitize(b), nil

总结,大多数I/O操作处理的是[]byte,而不是string. 当我们不是很明确到底是采用[]byte还是string时候,应想到本文举的例子,使用[]byte不一定没有string方便,像strings包提供的常用函数:Split、Count、Contains、Index 在bytes包中也有一样的函数。因此,在处理I/O操作时,我们应该首先想到使用[]byte而不是string,避免额外的转换开销。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-07-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据小冰 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Go语言中常见100问题-#88-2 the iotest package
iotest包 https://pkg.go.dev/testing/iotest 提供了测试 readers和writers 函数集合。很多Gopher不知道有这个包,本文讲如何使用该包,方便我们编写测试代码。
数据小冰
2023/08/17
2240
Go语言中常见100问题-#88-2 the iotest package
Go语言的IO库那么多,我该怎么选?
在计算机和信息技术领域里I/O这个术语表示输入 / 输出 ( 英语:Input / Output ) ,通常指数据在存储器(内部和外部)或其他周边设备之间的输入和输出,是信息处理系统与外部之间的通信。输入是系统接收的信号或数据,输出则是从其发送的信号或数据。
9号同学
2021/07/07
8830
Go语言的IO库那么多,我该怎么选?
Go语言中常见100问题-#96 Not knowing how to reduce allocations
减少内存分配是Go应用程序的一个常见优化事项。本系列文章已介绍了不少减少堆上内存分配的方法:
数据小冰
2024/02/01
1740
Go语言中常见100问题-#96 Not knowing how to reduce allocations
为什么要避免在 Go 中使用 ioutil.ReadAll?
ioutil.ReadAll 主要的作用是从一个 io.Reader 中读取所有数据,直到结尾。
AlwaysBeta
2022/01/06
2.9K0
Go语言核心36讲(Go语言实战与应用十八)--学习笔记
我们在前几篇文章中,主要讨论了strings.Builder、strings.Reader和bytes.Buffer这三个数据类型。
郑子铭
2021/11/30
3070
Go语言核心36讲(Go语言实战与应用十八)--学习笔记
Go语言中常见100问题-#46 Using a filename as a function input
在我们需要实现一个函数功能是读取一个文件的时候,将文件名传递给函数不是一种最佳的实践,可能产生一些反作用,比如在单元测试起来困难。下面将深入讨论这个问题并掌握怎么处理它。
数据小冰
2022/08/15
2540
Go错误集锦 | 字符串底层原理及常见错误
string是Go语言的基础类型,在实际项目中针对字符串的各种操作使用频率也较高。本文就介绍一下在使用string时容易犯的一些错误以及如何避免。
Go学堂
2023/01/31
4040
Go语言中常见100问题-#5 Interface pollution
在Go语言中,接口是我们设计和编写代码的基石。然而,像很多概念一样,滥用它是不好的。接口污染是指用不必要的抽象来编写代码(刻意使用接口),使得代码更难以理解。这是具有不同习惯,特别是有其它语言开发经验的人会犯的一个常见错误。在深入讨论接口污染之前,让我们重新梳理一下Go语言的接口,然后分析何时使用接口以及在什么时候使用会存在污染问题。
数据小冰
2022/12/18
4910
Go语言中常见100问题-#5 Interface pollution
golang-101-hacks(24)——Decorate types to implement io.Reader interface
io包提供了一组便捷的读取函数和方法,但同时都需要参数满足io.Reader接口。请看下面的例子:
羊羽shine
2019/07/01
7540
Go语言实战笔记(十九)| Go Writer 和 Reader
Go Writer 和 Reader接口的设计遵循了Unix的输入和输出,一个程序的输出可以是另外一个程序的输入。他们的功能单一并且纯粹,这样就可以非常容易的编写程序代码,又可以通过组合的概念,让我们的程序做更多的事情。
飞雪无情
2018/08/28
7720
【转】Go语言---strings包(字符串操作)
字符串求长度 求子串 是否存在某个字符或者子串 子串出现的次数(字符串匹配) 字符串分割(切分)成[]string 字符串是否存在某个前缀或后缀 字符或者子串在字符串中首次出现的位置或最后一次出现的位置 通过某个字符串将[]string进行拼接 字符串重复次数 字符串中子串替换 大小写转换 ......................等等一些基本操作。 由于string类型可以看成是一种特殊的slice类型,因此获取长度可以用内置的函数len;同时支持 切片 操作,因此,子串获取很容易。
yiduwangkai
2019/09/17
1K0
100 个 Go 错误以及如何避免:5~8
我们将在本章中看到 Go 有一个非常独特的处理字符串的方法。Go 引入了一个概念叫做符文;这个概念对于理解是必不可少的,可能会让新手感到困惑。一旦我们知道了字符串是如何被管理的,我们就可以避免在字符串上迭代时的常见错误。我们还将看看 Go 开发者在使用或生成字符串时所犯的常见错误。此外,我们会看到有时我们可以直接使用[]byte工作,避免额外的分配。最后,我们将讨论如何避免一个常见的错误,这个错误会造成子字符串的泄漏。本章的主要目的是通过介绍常见的字符串错误来帮助你理解字符串在 Go 中是如何工作的。
ApacheCN_飞龙
2023/10/13
1.1K0
100 个 Go 错误以及如何避免:5~8
Go语言中常见100问题-#79 Not closing transient resources
在程序开发中会经常使用临时资源,这些资源必须在代码中的某个位置进行关闭以防止泄露。例如,对于操作磁盘或内存的结构体,通常可以实现io.Closer接口来表达必须关闭临时资源。本文将深入分析三个常见的示例代码,说明资源如果没有正确关闭会产生什么问题以及如何处理它们。
数据小冰
2022/08/15
3530
[译] Golang Reader 接口实现
尽管本文探讨的是如何实现 io.Reader 接口,但是作为实现接口的一般套路也是有意义的。在讨论接口实现的这个主题时,我发现多数文章所列举的示例都脱离的现实,比如去实现一个 Animal 接口。
柳公子
2020/12/16
2.2K0
Go标准库:strings
Go 语言的 strings 包是标准库中的一个重要部分,专门用于操作字符串。它提供了丰富的字符串处理函数,涵盖了查找、比较、替换、分割、拼接、修剪等操作。在 Go 语言中,字符串是不可变的,strings 包提供的函数都不会修改原始字符串,而是返回新的字符串。
孟斯特
2024/08/11
2330
Go标准库:strings
Golang 语言标准库 bytes 包怎么使用?
Golang 语言中内置了两种字符类型,分别是 byte 的字节类类型,和 rune 的字符类类型。其中 byte 是 uint8 的别名,表示 ASCII 码的一个字符,占用 1 个字节,rune 是 int32 的别名,表示 UTF-8 字符,占用 4 个字节。
frank.
2021/02/07
1.7K0
golang讲解(go语言)标准库分析之strings结束篇
今天我们完结了这个strings的包,其实我们就剩下了type Reader和type Replacer这个我们之间讲过io的包,这样大家理解起来就比较省劲了! (1)func NewReader(s string) *Reader通过读取一个字符串之后返回Reader对象,然后实现io.Reader, io.ReaderAt, io.Seeker, io.ByteScanner, 和io.RuneScanner 接口 import ( "fmt" "reflect" "string
李海彬
2018/03/22
1.9K0
Golang标准库学习——buffio包 ---转
import "bufio" bufio包实现了有缓冲的I/O。它包装一个io.Reader或io.Writer接口对象,创建另一个也实现了该接口,且同时还提供了缓冲和一些文本I/O的帮助函数的对象。 一、常量 const ( // 用于缓冲一个token,实际需要的最大token尺寸可能小一些,例如缓冲中需要保存一整行内容 MaxScanTokenSize = 64 * 1024 ) 二、变量 var ( ErrInvalidUnreadByte = errors.New("bufi
李海彬
2018/03/20
1.6K0
Golang语言(打卡第四天)fmt格式化工具|Go主题月
Print系列函数会将内容输出到系统的标准输出,区别在于Print函数直接输出内容,Printf函数支持格式化输出字符串,Println函数会在输出内容的结尾添加一个换行符。
微芒不朽
2022/09/13
9430
Go标准库:bytes
Go 语言的标准库 bytes 包提供了一组用于操作字节切片 ([]byte) 的函数。这个包中的函数与 strings 包中的函数非常类似,但它们操作的是字节切片,而不是字符串。字节切片在 Go 语言中是一种非常重要的数据类型,广泛用于处理二进制数据和文本数据。bytes 包提供了很多处理字节切片的工具,包括但不限于查找、比较、切分、连接、替换、转换等操作。
孟斯特
2024/08/09
1700
Go标准库:bytes
推荐阅读
相关推荐
Go语言中常见100问题-#88-2 the iotest package
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验