英文:
How does Go resolve seemingly same types?
问题
我有一个包含两列的PostgreSQL数据库:id(UUID)和company_url(varchar),具有以下值:
2fc35af4-5f5c-445e-86c5-01d93513b8be | https://test.com
2bf31b75-d1f3-4a9c-a530-73b714816e9e | https://test2.com
以下是使用Go访问该表的代码(为简单起见,省略了错误处理和凭据):
package main
import (
"fmt"
"database/sql"
"github.com/google/uuid"
_ "github.com/lib/pq"
)
func main() {
connStr := "host= password= port= dbname= user="
db, _ := sql.Open("postgres", connStr)
rows, _ := db.Query("SELECT * FROM companies;")
for rows.Next() {
// var id [16]byte // not ok
var id uuid.UUID // ok
var companyURL string
rows.Scan(&id, &companyURL)
fmt.Println(id, companyURL)
}
}
还有一个用于UUID的Go包UUIDs。在其源代码中,UUID被简单地定义为:
type UUID [16]byte
在上面的代码中,id使用uuid.UUID进行了类型声明。我尝试在上面的代码中替换类型声明(使用not ok注释掉的部分),但返回的不是正确的值,而是一个由16个零组成的数组。而uuid.UUID返回正确的id。
所以我的问题是,如果uuid.UUID和[16]byte是相同类型的,为什么会出现这样的行为?uuid包中没有二进制文件,也没有init()函数,Scan()也没有进行任何隐式更改。
英文:
I have a PostgreSQL database with 2 columns: id (UUID), company_url (varchar) with following values:
2fc35af4-5f5c-445e-86c5-01d93513b8be | https://test.com
2bf31b75-d1f3-4a9c-a530-73b714816e9e | https://test2.com
Here's the code to access the table using Go (error handling and credentials omited for simplicity):
package main
import (
"fmt"
"database/sql"
"github.com/google/uuid"
_ "github.com/lib/pq"
)
func main() {
connStr := "host= password= port= dbname= user="
db, _ := sql.Open("postgres", connStr)
rows, _ := db.Query("SELECT * FROM companies;")
for rows.Next() {
// var id [16]byte // not ok
var id uuid.UUID // ok
var companyURL string
rows.Scan(&id, &companyURL)
fmt.Println(id, companyURL)
}
}
There also exists a Go package for UUIDs. In its' source code the UUID is defined simply as
type UUID [16]byte
In the code above the id is typed using uuid.UUID, I tried to replace the type declaration in my code above (commented out with not ok) but instead of the correct value it returns an array of 16 zeroes. uuid.UUID returns correct id.
So my question is why such behaviour if uuid.UUID and [16]byte are of the same types? There are no binaries in uuid package nor init() function, nor is Scan() making any implicit changes.
答案1
得分: 5
严格来说,它们不是相同的类型。不过它们有相同的底层类型。UUID不同之处在于它实现了接口sql.Scanner和driver.Valuer,因此可以透明地与数据库一起使用。
英文:
Strictly speaking, they are not the same types. They have the same underlying type though. UUID is different in that it implements the interfaces sql.Scanner and driver.Valuer, so it can be used with the databases transparently.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论