【问题标题】:Prevent runtime panic in bson.ObjectIdHex防止 bson.ObjectIdHex 中的运行时恐慌
【发布时间】:2018-12-10 08:14:53
【问题描述】:

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

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

我知道为什么,但是如果我输入错误/无效的输入字符串,我的应用程序就会出现运行时恐慌

我怎样才能防止这种情况发生?谢谢你

【问题讨论】:

    标签: mongodb go bson mgo


    【解决方案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...
    }
    

    【讨论】:

    • 为什么我得到bson.ObjectIdHex 错误undefined: bson.ObjectIdHex
    【解决方案2】:

    正如@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  
        }
    }
    

    【讨论】:

    • 这也是正确答案,但更复杂,谢谢!
    猜你喜欢
    • 2014-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-25
    • 1970-01-01
    • 2021-10-13
    • 2017-05-12
    相关资源
    最近更新 更多