Golang中bufio.NewReader将空格转换为加号的问题探讨
Golang中bufio.NewReader将空格转换为加号的问题探讨 我正在运行 go 版本 go1.12.1 windows/amd64 我的笔记本电脑是 Windows 10 64 位 我编写了一个 GO 程序,作为 Apache 网页服务器下的 CGI 脚本运行。
我的网页上的一个表单通过 POST 方法向 GOlang CGI 脚本程序提交了一个请求。
令我惊讶的是,数据字段中的空格被更改为了加号。
我使用 bufio.NewReader 来读取包含 POST 方法数据的标准输入,代码如下:
reader := bufio.NewReader(os.Stdin)
for {
looptext, _ := reader.ReadString('\n')
count := len(looptext)
if count == 0 {
break
}
post_data += looptext + "\n"
post_vars := strings.Split(looptext, "&")
for _, pvar := range post_vars {
pair := strings.SplitN(pvar, "=", 2)
fields_count += 1
fields_map[pair[0]] = pair[1]
}
} // FOR over lines of POST data
为什么空格被改成了加号?到目前为止,谷歌搜索还没有找到任何相关信息。
更多关于Golang中bufio.NewReader将空格转换为加号的问题探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html
感谢您的回复。我已经非常习惯使用 Perl 进行 CGI 编程,因为 Perl 的 CGI 库会为我处理所有的解码工作。
我添加了对 url.QueryUnescape() 的调用,现在数据完全符合预期。再次感谢。
更多关于Golang中bufio.NewReader将空格转换为加号的问题探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
请向我们展示POST请求的头部和主体。
同时,请查看百分比编码 - 维基百科
默认使用的编码基于早期版本的通用URI百分比编码规则,并进行了一些修改,例如换行符标准化以及**将空格替换为
+**而不是%20。
这是一个典型的表单编码问题,不是 bufio.NewReader 的转换。当表单通过 application/x-www-form-urlencoded 编码(默认编码)提交时,空格会被转换为加号(+)。
在 URL 编码规范中:
- 空格被编码为
+ - 其他特殊字符被编码为
%XX十六进制格式
你需要对接收到的值进行 URL 解码。使用 url.QueryUnescape() 函数:
package main
import (
"bufio"
"fmt"
"net/url"
"os"
"strings"
)
func main() {
fields_map := make(map[string]string)
reader := bufio.NewReader(os.Stdin)
for {
looptext, _ := reader.ReadString('\n')
looptext = strings.TrimRight(looptext, "\r\n")
if len(looptext) == 0 {
break
}
post_vars := strings.Split(looptext, "&")
for _, pvar := range post_vars {
pair := strings.SplitN(pvar, "=", 2)
if len(pair) == 2 {
// 解码 URL 编码的值
decodedValue, err := url.QueryUnescape(pair[1])
if err != nil {
decodedValue = pair[1] // 如果解码失败,使用原始值
}
fields_map[pair[0]] = decodedValue
}
}
}
// 测试输出
for key, value := range fields_map {
fmt.Printf("%s: %s\n", key, value)
}
}
或者,更简洁的方法是使用 url.ParseQuery():
package main
import (
"bufio"
"fmt"
"io"
"net/url"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
var input strings.Builder
// 读取所有输入
for {
line, err := reader.ReadString('\n')
if err != nil && err != io.EOF {
break
}
input.WriteString(line)
if err == io.EOF {
break
}
}
// 解析查询字符串
values, err := url.ParseQuery(input.String())
if err != nil {
fmt.Printf("解析错误: %v\n", err)
return
}
// 访问解码后的值
for key := range values {
fmt.Printf("%s: %s\n", key, values.Get(key))
}
}
如果你需要处理 multipart/form-data 编码(用于文件上传),则需要使用不同的方法:
package main
import (
"fmt"
"mime"
"mime/multipart"
"net/http"
"os"
"strings"
)
func main() {
// 从环境变量获取内容类型
contentType := os.Getenv("CONTENT_TYPE")
if strings.Contains(contentType, "multipart/form-data") {
// 处理 multipart 表单
reader := multipart.NewReader(os.Stdin, strings.Split(contentType, "boundary=")[1])
for {
part, err := reader.NextPart()
if err != nil {
break
}
defer part.Close()
// 处理每个部分
data := make([]byte, 1024)
n, _ := part.Read(data)
fmt.Printf("%s: %s\n", part.FormName(), string(data[:n]))
}
} else {
// 处理 application/x-www-form-urlencoded
// 使用上面的 url.ParseQuery 方法
}
}
关键点:
bufio.NewReader只是读取原始数据,不会修改内容- 空格变加号是表单提交时的标准 URL 编码行为
- 使用
url.QueryUnescape()或url.ParseQuery()进行解码 - 检查
CONTENT_TYPE环境变量来确定编码方式

