引言:为什么 "How to assign string to bytes array" 这个问题如此受欢迎?
\n\n如果你曾经用 Go (Golang) 编程,并且需要将普通字符串转换为字节数组 ([]byte),那么你并不孤单。Stack Overflow 上的问题 "How to assign string to bytes array" 获得了数万次浏览。看起来很简单,对吧?直接赋值就行了。但 Go 是一种强类型语言,你不能简单地将字符串直接赋值给字节切片。你需要掌握正确的技术。
在本文中,我们将深入探讨 Go 中的 字符串到字节数组的转换。我将向你展示三种主要方法:从最简单的方法开始,到超快但危险的方法。你将了解如何根据任务选择合适的方法,并且再也不会在这些转换中感到困惑。
\n\n我们开始吧!
\n\n一点理论:为什么字符串不是字节数组?
\n\n在开始写代码之前,让我们先弄清楚为什么 Go 要区分这两种类型。了解这一点可以帮你避免许多错误。
\n\n- \n
- string 在 Go 中是一个不可变的 (immutable) 字节序列。你不能通过索引更改字符串中的字符。字符串始终作为只读内存块存储。 \n
- []byte 是一个可变的 (mutable) 字节切片。你可以修改其内容、添加新元素等。 \n
正是由于这种“不可变性”的差异,Go 要求进行显式转换。如果编译器允许直接将字符串赋值给字节数组,你可能会意外修改字符串的“受保护”数据。因此,将字符串赋值给字节数组始终需要你明确的操作。
\n\n方法 #1:显式类型转换(最简单)
\n\n这是每个新手首先想到的方法。而且它确实有效!
\n\npackage main\n\nimport "fmt"\n\nfunc main() {\n myString := "Привет, Go!"\n myBytes := []byte(myString)\n\n fmt.Println(myBytes) // [208 159 209 128 ...] — UTF-8 编码的字节\n fmt.Println(string(myBytes)) // 转换回来:"Привет, Go!"\n}\n\n\n优点:
\n- \n
- 非常简单且可读性强。 \n
- 标准方法,任何 Go 开发者都能理解。 \n
缺点:
\n- \n
- 在内存中创建数据的新副本。如果字符串非常大(例如 10 MB),可能会在内存和时间上造成较大开销。 \n
- 不适用于对每一纳秒都至关重要的高负载系统。 \n
何时使用: 在 90% 的情况下。对于普通应用程序、Web 服务和脚本来说,这已经足够了。不要在不必要的地方进行优化。
\n\n方法 #2:使用 copy()(可控)
\n\n有时你已经预先分配了一个字节数组,并希望用字符串中的数据填充它。这时可以使用 copy 函数。
package main\n\nimport "fmt"\n\nfunc main() {\n myString := "Go is awesome"\n \n // 创建一个所需长度的字节切片\n myBytes := make([]byte, len(myString))\n \n // 将字符串中的数据复制到切片中\n n := copy(myBytes, myString)\n \n fmt.Printf("复制的字节数:%d\\n", n) // 13\n fmt.Println(string(myBytes)) // "Go is awesome"\n}\n\n\n请注意:copy 只复制目标切片能容纳的字节数。如果目标切片比字符串短,则只复制其长度。如果你不确定大小,这比显式转换更安全。
优点:
\n- \n
- 完全控制复制过程。 \n
- 安全性:不会超出数组边界。 \n
- 可用于部分复制(子字符串)。 \n
缺点:
\n- \n
- 需要预先分配内存 (
make)。 \n - 仍然会创建数据的副本。