Go语言中“读字符串”本质是从源读字节再转string:小文件用os.ReadFile(Go 1.16+),大文本用bufio.Scanner按行处理,标准输入/网络需注意换行符和UTF-8校验,遍历字符必须用rune而非字节下标。

Go 语言里没有“读字符串”这个独立动作——字符串是值,不是流。你真正要做的,是「从某处(文件、网络、内存)拿到字节,再转成 string」。关键在来源和方式,而不是字符串本身。
用 os.ReadFile 读小文本文件(推荐,Go 1.16+)
这是最直接的方式,适合配置文件、模板、JSON 等 ≤ 几 MB 的内容。
-
os.ReadFile返回[]byte和error,不处理编码,只管读字节 - 转字符串只需
string(data),前提是源文件是 UTF-8(含 BOM);GBK 等需额外解码 - 若文件不存在或权限不足,
err非 nil,必须检查,不能忽略 - 别用
ioutil.ReadFile(已弃用),Go 1.16+ 编译会警告
示例:
data, err := os.ReadFile("config.txt")
if err != nil {
log.Fatal(err)
}
content := string(data) // 直接转,无拷贝开销
用 bufio.Scanner 按行读大文本或流式内容
当文件可能很大(几十 MB 以上)、或你只需要逐行处理(如日志分析、CSV 解析),就别一次性加载进内存。
立即学习“go语言免费学习笔记(深入)”;
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
-
strings.NewReader(s)把已有字符串转成io.Reader,才能喂给bufio.Scanner -
scanner.Text()返回当前行(不含换行符),scanner.Bytes()返回原始字节切片 - 默认单行最大 64KB,超长会报
bufio.Scanner: token too long;需支持更长行,得调scanner.Buffer - 记得最后检查
scanner.Err(),否则 I/O 错误会被静默吞掉
示例:
scanner := bufio.NewScanner(strings.NewReader(myString))
for scanner.Scan() {
line := scanner.Text()
// 处理 line...
}
if err := scanner.Err(); err != nil {
log.Fatal(err) // 这步常被漏掉
}
从标准输入或网络读字符串要注意什么
这类场景本质仍是读字节流,但容易踩编码和截断坑。
-
fmt.Scanln或fmt.Scanf会按空白符分割,不适合读含空格的整行 - 读整行请用
bufio.NewReader(os.Stdin).ReadString('\n'),但返回值含\n,需strings.TrimSuffix去掉 - HTTP body 等网络响应体,建议先用
io.ReadAll(非io.Read单次调用),避免只读一部分就结束 - 所有从外部读入的字节,都应校验是否合法 UTF-8(
utf8.Valid),否则range字符串或len可能行为异常
字符串内部“读字符”要用 rune,别用下标
Go 的 string 是字节序列,s[0] 取的是第一个字节,不是第一个字符——尤其遇到中文、emoji 时必然错。
- 要遍历字符,必须用
for _, r := range s,r类型是rune(即int32) - 要取第 N 个字符?得先转成
[]rune:runes := []rune(s); char := runes[n],但注意这会分配新切片 -
len(s)返回字节数,utf8.RuneCountInString(s)才是字符数;二者通常不等 - 正则匹配、子串提取等操作,也建议基于
rune逻辑做,而非字节偏移
最易被忽略的一点:字符串不可变,所有“修改”操作(如替换、截取)都返回新字符串,底层字节可能共享也可能不共享——别假设 string 和 []byte 内存布局一致,更别试图用 unsafe 强转去改它。

















