英文:
Age() function not working with time.Time
问题
尝试使用PostgreSQL的age()函数与DateOfBirth一起使用,但出现了错误。错误信息是"Unsupported Scan, storing driver.Value type []uint8 into type *time.Time"。
如果我将DOB作为字符串传递,age()函数可以正常工作。但是,我想检查DOB的有效性,所以我使用了time.Parse("2006-01-02", DOB)函数。
在createPerson函数中,我解析了表单数据并获取了dob字段的值。然后,我使用time.Parse("2006-01-02", dob)将其转换为时间类型。
在getPerson函数中,我将URL参数id转换为整数,并使用models.person.Get(id)获取相应的person对象。
以上是要翻译的内容。
英文:
Trying to use age() function from postgresql with DateOfBirth
type Person struct {
ID int
DOB time.Time
}
query := `SELECT id, AGE(dateofbirth) from person WHERE id = $1`
But got an error
> Unsupported Scan, storing driver.Value type []uint8 into type *time.Time
The age() function work if I just pass the DOB as string
type Person struct {
ID int
DOB string
}
But I want to check the validity of DOB so I use time.Parse("2006-01-02", DOB)
func createPerson(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm()
if err != nil {
log.Fatal(err)
}
dob := r.PostForm.Get("dob")
birthday, _ := time.Parse("2006-01-02", dob)
err = models.person.Insert(birthday)
if err != nil {
log.Fatal("Server Error: ", err)
return
}
http.Redirect(w, r, "/", http.StatusSeeOther)
}
func getPerson(w http.ResponseWriter, r *http.Request) {
id, err := strconv.Atoi(chi.URLParam(r, "id"))
if err != nil {
log.Fatal("Not found", err)
return
}
person, err = models.person.Get(id)
if err != nil {
log.Fatal("Server Error: ", err)
return
}
render.HTML(w, http.StatusOK, "person.html", person)
}
答案1
得分: 0
你的数据库驱动程序负责将来自数据库的数据转换为Go数据类型。我假设你正在使用pq
驱动程序,它有以下关于数据类型的规则:
- 小整数类型smallint、整数类型integer和大整数类型bigint会被返回为int64类型。
- 浮点数类型real和double precision会被返回为float64类型。
- 字符类型char、varchar和text会被返回为string类型。
- 日期时间类型date、time、timetz、timestamp和timestamptz会被返回为time.Time类型。
- 布尔类型会被返回为bool类型。
- bytea类型会被返回为[]byte类型。
所有其他类型会直接从后端以文本格式返回为[]byte值。
在PostgreSQL中,AGE
函数返回的数据类型是interval
。这不是直接支持的数据类型之一,所以pq
将其处理为[]byte
。这就是为什么当你将DOB
设置为string
时它能正常工作。在Go中,[]byte
和string
之间的转换非常简单,所以驱动程序能够填充该值。
驱动程序无法将[]byte
填充到time.Time
值中,因为它不知道要使用哪个转换程序。实际上,没有直接的转换程序,因为interval
表示的是一段时间的持续时间,而time.Time
表示的是时间的实例。interval
更类似于time.Duration
值。然而,驱动程序不支持从interval
到任何类型的自动转换,我也不知道如何添加新的转换方式。你需要在从数据库获取数据后自己实现转换。
你也可以切换到pgx
驱动程序,它支持Interval
类型。
英文:
Your database driver is responsible for transforming the incoming data from the database into Go data types. I'll assume you're using pq
, which has the following rules about data types:
> This package returns the following types for values from the PostgreSQL backend:
>
> - integer types smallint, integer, and bigint are returned as int64
> - floating-point types real and double precision are returned as float64
> - character types char, varchar, and text are returned as string
> - temporal types date, time, timetz, timestamp, and timestamptz are returned as time.Time
> - the boolean type is returned as bool
> - the bytea type is returned as []byte
>
> All other types are returned directly from the backend as []byte values in text format.
In PostgreSQL, the AGE
function returns data type interval
. This is not one of the directly supported data types, so pq
processes it as []byte
. That is why it works when you make DOB
a string
. Conversion between []byte
and string
in Go is trivial, so the driver is able to fill in the value.
The driver fails to fill the []byte
into a time.Time
value because it doesn't know what conversion routine to use. Actually, there is no direct conversion routine because interval
represents a duration of time, while time.Time
represents an instance of time. interval
is more analogous to a time.Duration
value. Still, the driver doesn't support any automatic conversion from interval
to any type, and I'm not aware of a way to add a new conversion. You would have to implement the conversion yourself after fetching the data from the database.
You could also switch to the pgx
driver, which supports an Interval
type.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论