繁体   English   中英

如何在 Golang 应用程序中正确使用 UUID4?

[英]How correctly use UUID4 in Golang application?

我是Golang ,需要一些帮助! 我有几个问题。

PostgreSQL数据库中,我有一个名为surveys表。

CREATE TABLE SURVEYS(
  SURVEY_ID UUID PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
  SURVEY_NAME VARCHAR NOT NULL,
  SURVEY_DESCRIPTION TEXT,
  START_PERIOD TIMESTAMP,
  END_PERIOD TIMESTAMP
);

如您所见, SURVEY_ID列是PRIMARY KEY ,它的类型是UUID4

Golang应用程序中,我为此表创建了这样的struct

type Survey struct {
    ID string `json:"survey_id"`
    Name string `json:"survey_name"`
    Description utils.NullString `json:"survey_description"`
    StartPeriod utils.NullTime `json:"start_period"`
    EndPeriod utils.NullTime `json:"end_period"`
}

如您所见, ID 字段的类型是string 这是正确的吗? 我不确定这是最佳实践。

我的第二个问题是关于通过 ID 向特定调查发出GET请求时GET奇怪结果。

例如,当我提出这样的要求时:

http://localhost:8000/api/survey/0cf1cf18-d5fd-474e-a8be-754fbdc89720

作为回应,我有这个:

{
    "survey_id": "0cf1cf18-d5fd-474e-a8be-754fbdc89720",
    "survey_name": "NAME",
    "survey_description": {
        "String": "DESCRIPTION",
        "Valid": true
    },
    "start_period": {
        "Time": "2019-01-01T00:00:00Z",
        "Valid": false
    },
    "end_period": {
        "Time": "0001-01-01T00:00:00Z",
        "Valid": false
    }
}

如您所见,最后 3 个字段有问题: survey_descriptionstart_periodend_period 我想在一行中看到键和值。 例如这里:

{
    "survey_id": "0cf1cf18-d5fd-474e-a8be-754fbdc89720",
    "survey_name": "NAME",
    "survey_description": "DESCRIPTION",
    "start_period": "2019-01-01 00:00:00",
    "end_period": null
}

我在代码中到底哪里出错了?

实用工具去:

package utils

import (
    "database/sql"
    "encoding/json"
    "fmt"
    "github.com/lib/pq"
    "time"
)

// NullTime is an alias for pq.NullTime data type.
type NullTime struct {
    pq.NullTime
}

// MarshalJSON for NullTime.
func (nt *NullTime) MarshalJSON() ([]byte, error) {
    if !nt.Valid {
        return []byte("null"), nil
    }
    val := fmt.Sprintf("\"%s\"", nt.Time.Format(time.RFC3339))
    return []byte(val), nil
}

// UnmarshalJSON for NullTime.
func (nt *NullTime) UnmarshalJSON(b []byte) error {
    err := json.Unmarshal(b, &nt.Time)
    nt.Valid = err == nil
    return err
}

// NullInt64 is an alias for sql.NullInt64 data type.
type NullInt64 struct {
    sql.NullInt64
}

// MarshalJSON for NullInt64.
func (ni *NullInt64) MarshalJSON() ([]byte, error) {
    if !ni.Valid {
        return []byte("null"), nil
    }
    return json.Marshal(ni.Int64)
}

// UnmarshalJSON for NullInt64.
func (ni *NullInt64) UnmarshalJSON(b []byte) error {
    err := json.Unmarshal(b, &ni.Int64)
    ni.Valid = err == nil
    return err
}

// NullString is an alias for sql.NullString data type.
type NullString struct {
    sql.NullString
}

// MarshalJSON for NullString.
func (ns *NullString) MarshalJSON() ([]byte, error) {
    if !ns.Valid {
        return []byte("null"), nil
    }
    return json.Marshal(ns.String)
}

// UnmarshalJSON for NullString.
func (ns *NullString) UnmarshalJSON(b []byte) error {
    err := json.Unmarshal(b, &ns.String)
    ns.Valid = err == nil
    return err
}

路线.go:

router.HandleFunc("/api/survey/{survey_id:[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}}", controllers.GetSurvey).Methods("GET")

控制器/survey.go:

var GetSurvey = func(responseWriter http.ResponseWriter, request *http.Request) {
    // Initialize variables.
    survey := models.Survey{}
    var err error

    vars := mux.Vars(request)

    // Execute SQL statement.
    err = database.DB.QueryRow("SELECT * FROM surveys WHERE survey_id = $1;", vars["survey_id"]).Scan(&survey.ID, &survey.Name, &survey.Description, &survey.StartPeriod, &survey.EndPeriod)

    // Shape the response depending on the result of the previous command.
    if err != nil {
        log.Println(err)
        switch err {
        case sql.ErrNoRows:
            utils.ResponseWithError(responseWriter, http.StatusNotFound, "The entry not found.")
        default:
            utils.ResponseWithError(responseWriter, http.StatusInternalServerError, err.Error())
        }
        return
    }
    utils.Response(responseWriter, http.StatusOK, survey)
}

嗯,最后我找到了结果。

我改变了表的结构:

type Survey struct {
    ID string `json:"survey_id"`
    Name string `json:"survey_name"`
    Description *string `json:"survey_description", sql:"index"`
    StartPeriod *time.Time `json:"start_period", sql:"index"`
    EndPeriod *time.Time `json:"end_period", sql:"index"`
}

我认为使用string作为 UUID 没有任何问题。

至于MarshalJSON不起作用,我想我知道发生了什么。 您的空类型不实现 MarshalJSON,只有指向它们的指针。 解决方法是将函数更改为使用非指针接收器,或者在结构中使字段成为指针。

func (ns *NullString) MarshalJSON() ([]byte, error)

如果你确实让它们成为指针,那么你可以保持它们那样,因为它们可以为空。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM