在数据库golang中保存帖子数据(带有整数和字符串值)的正确方法是什么?

在数据库golang中保存帖子数据(带有整数和字符串值)的正确方法是什么?

问题描述:

I've the following golang code:

package main

import (
    "github.com/gin-gonic/gin"
    "gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
    "log"
    "time"
)

func main() {
    router := gin.Default()
    router.POST("/save-address", SaveAddress)
    router.Run()
}

func SaveAddress(c *gin.Context){
    var err error
    conditions := bson.M{}
    c.Request.ParseForm()
    for key, _ := range c.Request.PostForm {
        if key != "id"{
            conditions[key] = c.PostForm(key)
        }
    }
    conditions["_id"] = 1
    mongoSession := ConnectDb()

    sessionCopy := mongoSession.Copy()
    defer sessionCopy.Close()

    getCollection := mongoSession.DB("bformssettings").C("address")
    err = getCollection.Insert(conditions)
    if err != nil{
        println(err)
    }else{
        println("Data saved successfully!!!")
    }
}
func ConnectDb() (mongoSession *mgo.Session) {
    mongoDBDialInfo := &mgo.DialInfo{
        Addrs:    []string{"localhost:27017"},
        Timeout:  60 * time.Second,
        Database: "bformssettings",
    }

    mongoSession, err := mgo.DialWithInfo(mongoDBDialInfo)
    if err != nil {
        log.Fatalf("CreateSession: %s
", err)
    }

    mongoSession.SetMode(mgo.Monotonic, true)

    return mongoSession
}

When I run the code, data of the following format will be saved in the database:

{ "_id" : 1, "customer_id" : "3", "address" : "Chicago, IL", "city" : "Chicago", "state" : "IL", "zipcode" : "60647" }

Problem:

customer_id is an integer value, but it will be saved as string in the database.

Possible workaround:

It is possible to reconvert the string representation of id back to integer before saving it in the database.

Question:

Is there another way to save data as it is? E.g. to save integer values as integer values?

If you look at your saved document, you can see it's _id property is already a number (and not a string), so yes, this is definitely possible.

The reason why you end up with a customer_id property being of type string is because the document you save (conditions variable) holds a string value for customer_id property. And it is of type string because you filled it with the return value of Context.PostForm() which returns a form value as a string.

If you want it to be an integer in the database, convert it to a Go integer before setting it in conditions. For that you may use strconv.Atoi() for example.

for key, _ := range c.Request.PostForm {
    value := c.PostForm(key)
    if key == "customer_id" {
        if id, err := strconv.Atoi(value); err != nil {
            // Not a valid number, handle error
        } else {
            conditions[key] = id
        }
    } else {
        if key != "id"{
            conditions[key] = value
        }
    }
}

You have to define somehow which fields are supposed to hold integer values. I just showed a way to do that with a single field. If you have multiple of them, you may list them in a slice, and use a single for loop to detect / handle all; or even better, put them in a map that acts as a set, and you can detect these fields without a for loop.

Another option would be to create a struct type modeling your form input data, and use a library like Gorilla's schema to unmarshal into that struct in a type-aware manner.