防止bson.ObjectIdHex中的运行时出现紧急情况

时间:2018-12-10 08:14:53

标签: mongodb go bson mgo

我正在尝试使用mgo将objectid字符串转换为bson ObjectId格式,

errCheck := d.C("col").FindId(bson.ObjectIdHex(obid[0])).One(&Result)

idk为什么,但是如果我输入了错误/无效的输入字符串,我的应用程序就会出现运行时崩溃

我该如何预防?谢谢

2 个答案:

答案 0 :(得分:1)

bson.ObjectIdHex()文档记录了如果传递无效的对象ID将会恐慌的情况:

  

ObjectIdHex从提供的十六进制表示中返回一个ObjectId。 以无效的十六进制表示形式调用此函数将导致运行时出现紧急情况。请参见IsObjectIdHex函数。

如果要避免这种情况,请首先使用bson.IsObjectIdHex()检查输入字符串,然后仅在输入有效的情况下才继续调用bson.ObjectIdHex()

if bson.IsObjectIdHex(obid[0]) {
    // It's valid, calling bson.ObjectIdHex() will not panic...
}

答案 1 :(得分:0)

如@icza在最后一个答案中所述。您应该检查ObjectId是否有效。 而且您将来可以使用panic recover defer处理任何类型的错误

package main

import (
    "fmt"
    "gopkg.in/mgo.v2/bson"
    "path/filepath"
    "runtime"
    "strings"
)

func main() {
    r := Result{}
    getData(&r)
}

func IdentifyPanic() string {
    var name, file string
    var line int
    var pc [16]uintptr

    n := runtime.Callers(3, pc[:])
    for _, pc := range pc[:n] {
        fn := runtime.FuncForPC(pc)
        if fn == nil {
            continue
        }
        file, line = fn.FileLine(pc)
        name = fn.Name()

        if !strings.HasPrefix(name, "runtime.") {
            break
        }
    }
    file = filepath.Base(file)

    switch {
    case name != "":
        return fmt.Sprintf("%v:%v", file, line)
    case file != "":
        return fmt.Sprintf("%v:%v", file, line)
    }

    return fmt.Sprintf("pc:%x", pc)
}

type Result struct {
    success int
    data string
}
func getData(result *Result){
    defer func() {
        if err := recover(); err != nil {
            ip := IdentifyPanic()
            errorMessage := fmt.Sprintf("%s Error: %s", ip, err)
            fmt.Println(errorMessage)
            result.success = 0
        }
    }()
    if bson.IsObjectIdHex(obid[0]) {                                 // this line copied from @icza answer
        // It's valid, calling bson.ObjectIdHex() will not panic...  // this line copied from @icza answer
        errCheck := d.C("col").FindId(bson.ObjectIdHex(obid[0])).One(&res)
        result.success = 1
        result.data = "your result (res). this is just the exam"
    }else{
        result.success = 0  
    }
}