最近在使用 Golang 开发 Web 应用时,碰到一个问题。
我编写了一个用于过滤人员认证列表的接口。
http://127.0.0.1:11088/api/v1/person-auths?status=0,2
复制代码
其中 status 字段是一个过滤条件。比如 0,2 就是查询所有 status 为 0 和 2 的人员认证记录。
在 gin 框架中,可以使用 ctx.Query 获取到 status 对应的字符串。
statusStr := ctx.Query("status")// 1,2
复制代码
业务逻辑层的查询参数结构体类型定义的是这样的:
type PersonAuthQueryParam struct {
Status []int
// ...
}
复制代码
所以我需要将字符串 1,2 转换为 int 类型的切片 [1, 2]。
按照 JavaScript 的习惯,这非常简单。
statusStr := "1,2"
statusStrs := strings.Split(statusStr, ",")
var statusInts []int
for i, v := range statusStrs {
vInt, err := strconv.Atoi(v)
if err != nil {
return err
}
statusInts[i] = vInt
}
复制代码
逻辑上是将字符串以 , 分割为一个 string 切片,然后创建一个空的 int 切片。
遍历 string 切片,将每一个元素的类型转换为 int,并赋值给 int 切片对应的下标上面。
但是在实际运行时,会得到一个 runtime error。
panic: runtime error: index out of range [0] with length 0
复制代码
这是一个标准的数组越界问题。
因为此时的 int 切片是空切片,长度和容量都为 0。
fmt.Printf("%v\n", len(statusInts))// 0
fmt.Printf("%v\n", cap(statusInts))// 0
fmt.Printf("%v\n", statusInts == nil)// true
复制代码
解决的方法有两种。
第一种是换一种添加元素的方式。
使用 append 函数添加元素,它会自动扩容。
statusInts = append(statusInts, vInt)
复制代码
第二种是换一种初始化切片的方式,给切片设置一个 length。
statusInts := make([]int, len(statusStrs))
复制代码