Go sqlx库提供奇怪的base64编码结果

Go sqlx库提供奇怪的base64编码结果,go,Go,我正在从使用此库进行查询。根据文档,我找到了下面的代码 func cities(w http.ResponseWriter, r *http.Request, _ httprouter.Params) error { var main string var secondary string var limit string queryParams := make(map[string]interface{}) if k := r.PostFormValu

我正在从使用此库进行查询。根据文档,我找到了下面的代码

func cities(w http.ResponseWriter, r *http.Request, _ httprouter.Params) error {
    var main string
    var secondary string
    var limit string
    queryParams := make(map[string]interface{})

    if k := r.PostFormValue("keyword"); k != "" {
        main = "city.name LIKE :keyword"
        queryParams["keyword"] = k + "%"
    }

    if sk := r.PostFormValue("secondaryKeyword"); sk != "" && sk != "null" {
        secondary = "OR city.name = :secondaryKeyword"
        queryParams["secondaryKeyword"] = sk
    }

    if mr := r.PostFormValue("maxResults"); mr != "" {
        limit = "LIMIT :maxResults"
        queryParams["maxResults"] = mr
    }

    if lr := r.PostFormValue("lastRequest"); lr != "" && lr == "1" {
        limit = ""
    }

    query := fmt.Sprintf(`
        SELECT
            city.geonameid AS cityId,
            city.name AS cityName,
            COALESCE(admin1.name_local, '') AS admin1Name,
            country.name AS countryName,
            CONCAT_WS(' ', city.name, city.asciiname, country.name) AS searchString
        FROM geonames_cities1000 AS city
            INNER JOIN geonames_countryinfo AS country
                ON city.iso_alpha2 = country.iso_alpha2
            LEFT OUTER JOIN geonames_admin1_codes_ascii as admin1
                ON admin1.code = CONCAT(city.iso_alpha2, '.', city.admin1_code)
        WHERE %s %s
        ORDER BY city.name ASC %s;
    `, main, secondary, limit)

    nstmt, err := sql.DB.PrepareNamed(query)
    if err != nil {
        return err
    }

    rows, err := nstmt.Queryx(queryParams)
    if err != nil {
        return err
    }

    results := []interface{}{}

    for rows.Next() {
        row := make(map[string]interface{})
        err := rows.MapScan(row)
        if err != nil {
            return err
        }
        results = append(results, row)
    }

    b, err := json.Marshal(results)
    if err != nil {
        return err
    }
    w.Write(b)
    return nil
}
发送具有以下值的POST request postman chrome插件:

keyword: "tron"
maxResults: 7
lastRequest: 0
给出了此JSON输出:

[
    {
        "admin1Name": "VXR0YXJhZGl0",
        "cityId": 1605268,
        "cityName": "VHJvbg==",
        "countryName": "VGhhaWxhbmQ=",
        "searchString": "VHJvbiBUcm9uIFRoYWlsYW5k"
    },
    {
        "admin1Name": "Q2FsYWJyaWE=",
        "cityId": 8949073,
        "cityName": "VHJvbmNh",
        "countryName": "SXRhbHk=",
        "searchString": "VHJvbmNhIFRyb25jYSBJdGFseQ=="
    },
    {
        "admin1Name": "QXJhZ29u",
        "cityId": 3107444,
        "cityName": "VHJvbmNow7Nu",
        "countryName": "U3BhaW4=",
        "searchString": "VHJvbmNow7NuIFRyb25jaG9uIFNwYWlu"
    },
    {
        "admin1Name": "UHVlYmxh",
        "cityId": 8859151,
        "cityName": "VHJvbmNvbmFs",
        "countryName": "TWV4aWNv",
        "searchString": "VHJvbmNvbmFsIFRyb25jb25hbCBNZXhpY28="
    },
    {
        "admin1Name": "U2NobGVzd2lnLUhvbHN0ZWlu",
        "cityId": 2821000,
        "cityName": "VHLDtm5kZWw=",
        "countryName": "R2VybWFueQ==",
        "searchString": "VHLDtm5kZWwgVHJvbmRlbCBHZXJtYW55"
    },
    {
        "admin1Name": "U8O4ci1UcsO4bmRlbGFn",
        "cityId": 3133880,
        "cityName": "VHJvbmRoZWlt",
        "countryName": "Tm9yd2F5",
        "searchString": "VHJvbmRoZWltIFRyb25kaGVpbSBOb3J3YXk="
    },
    {
        "admin1Name": "VG9uZ3Nh",
        "cityId": 1252408,
        "cityName": "VHJvbmdzYQ==",
        "countryName": "Qmh1dGFu",
        "searchString": "VHJvbmdzYSBUcm9uZ3NhIEJodXRhbg=="
    }
]
为什么结果是这样?将结果放入spew.Dump()中 将给出如下内容(我只是输出其中一行):

我在这里做错了什么?”

编辑:

我试着用structs代替Elwinar的建议。但有些事情真的很奇怪

此代码适用于:

type City struct {
    AdminName    string `json:"admin1Name"   db:"admin1Name"`
    CityID       int64  `json:"cityId"       db:"cityId"`
    CityName     string `json:"cityName"     db:"cityName"`
    CountryName  string `json:"countryName"  db:"countryName"`
    SearchString string `json:"searchString" db:"searchString"`
}
但此代码不起作用,并输出错误“缺少目标名称cityId”:

有什么区别


解决方案:必须用空格键分隔标签。不能使用tab键进行空格,也不能使用逗号分隔标记。

包编码/json将封送
[]字节
切片base64编码(请参阅)。所以问题就出在通过
json.Marshal(results)
的输出中

在某个地方,您的代码调用一个函数,该函数生成一个
[]字节
,该字节很好地隐藏在其中一个
{}接口
中。去掉每个空接口,在适当的地方使用字符串,问题要么消失,要么解决方案显而易见


(调用
json.marshall
并出于调试目的输出结果可能不是一个好主意,尤其是如果您不知道实际的封送是什么。)

正如
spew.Dump
告诉您的那样,SQL驱动程序返回文本列的
[]uint8
。事实上,它相当于
[]字节
,它将
json.Marshal
编码为base64字符串

解决这一问题的最简单方法是将行扫描到一个真正的结构中(sqlx在
StructScan
方面做得很好),该结构将具有
string
字段,以便
json.Marshal
按预期显示它们。您可以使用标记控制字段的SQL和JSON名称,这样您的实体就可以有每种语言的约定名称

例如:

type City struct {
    AdminName    string `json:"admin1Name"   sql:"admin1Name"`
    CityID       int64  `json:"cityId"       sql:"cityId"`
    CityName     string `json:"cityName"     sql:"cityName"`
    CountryName  string `json:"countryName"  sql:"countryName"`
    SearchString string `json:"searchString" sql:"searchString"`
}

在您的数据库架构中,哪种类型是,例如,
countryName
?我尝试过这样做,但不断出现“缺少目标名称cityId”错误。好了,现在可以了,我需要将sql标记更改为db标记!谢谢顺便问一句,您知道我是否应该推迟rows.Close()和额外的err=rows.err()检查,正如这里强调的:我一直得到“缺少目标名称cityId”错误当结构没有与结果列匹配的字段时,会发生此错误。因此,请仔细检查标记(我不记得它是
db
还是
sql
,我用了很长时间)和结果名称。这件事…
type City struct {
    CityId       int64  `json:"cityId"       db:"cityId"`
    CityName     string `json:"cityName"     db:"cityName"`
    Admin1Name   string `json:"admin1Name"   db:"admin1Name"`
    CountryName  string `json:"countryName"  db:"countryName"`
    SearchString string `json:"searchString" db:"searchString"`
}
type City struct {
    AdminName    string `json:"admin1Name"   sql:"admin1Name"`
    CityID       int64  `json:"cityId"       sql:"cityId"`
    CityName     string `json:"cityName"     sql:"cityName"`
    CountryName  string `json:"countryName"  sql:"countryName"`
    SearchString string `json:"searchString" sql:"searchString"`
}