我知道使用自定义类型是一个常见问题,但请耐心等待...
我想定义一个自定义类型“ConnectionInfo”(见下文):
type DataSource struct {
gorm.Model
Name string
Type DataSourceType `sql:"type:ENUM('POSTGRES')" gorm:"column:data_source_type"`
ConnectionInfo ConnectionInfo `gorm:"embedded"`
}
我想将 ConnectionInfo 限制为有限数量的类型之一,即:
type ConnectionInfo interface {
PostgresConnectionInfo | MySQLConnectionInfo
}
我该怎么做?
到目前为止我的进展:
我定义了一个 ConnectionInfo 接口(interface)(我现在知道这在 GORM 中是无效的,但我如何解决它?)
type ConnectionInfo interface {
IsConnectionInfoType() bool
}
然后我用两种类型实现了这个接口(interface)(并实现了扫描仪和评估器接口(interface)),如下所示:
type PostgresConnectionInfo struct {
Host string
Port int
Username string
Password string
DBName string
}
func (PostgresConnectionInfo) IsConnectionInfoType() bool {
return true
}
func (p *PostgresConnectionInfo) Scan(value interface{}) error {
bytes, ok := value.([]byte)
if !ok {
return fmt.Errorf("failed to unmarshal the following to a PostgresConnectionInfo value: %v", value)
}
result := PostgresConnectionInfo{}
if err := json.Unmarshal(bytes, &result); err != nil {
return err
}
*p = result
return nil
}
func (p PostgresConnectionInfo) Value() (driver.Value, error) {
return json.Marshal(p)
}
但是我当然收到以下错误:
unsupported data type: /models.ConnectionInfo
最佳答案
您可以采用这种方式来代替使用此联合 GITHUB LINK 。您可以克隆这些存储库并运行代码。这是有效的。
package storage
import (
"database/sql/driver"
"encoding/json"
"fmt"
"log"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type DataSourceType string
const (
POSTGRES DataSourceType = "POSTGRES"
MYSQL DataSourceType = "MYSQL"
)
type PostgresConnectionInfo struct {
Host string
Port int
Username string
Password string
DBName string
}
type MySQLConnectionInfo struct {
Host string
Port int
Username string
Password string
DBName string
}
type ConnectionInfo struct {
Postgres *PostgresConnectionInfo `gorm:"-" json:"postgres,omitempty"`
Mysql *MySQLConnectionInfo `gorm:"-" json:"mysql,omitempty"`
}
type DataSource struct {
gorm.Model
Name string
Type DataSourceType `sql:"type:ENUM('POSTGRES')" gorm:"column:data_source_type"`
ConnectionInfo ConnectionInfo `gorm:"type:json" `
}
func (a *ConnectionInfo) Scan(src any) error {
switch src := src.(type) {
case nil:
return nil
case []byte:
var res ConnectionInfo
err := json.Unmarshal(src, &res)
*a = res
return err
default:
return fmt.Errorf("scan: unable to scan type %T into struct", src)
}
}
func (a ConnectionInfo) Value() (driver.Value, error) {
ba, err := json.Marshal(a)
return ba, err
}
func GormTest2() {
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})
if err != nil {
log.Fatal("could not open database")
}
err = db.AutoMigrate(&DataSource{})
if err != nil {
log.Fatal("could not migrate database")
}
createTestData1(db)
fetchData1(db)
}
func createTestData1(db *gorm.DB) {
ds := []DataSource{
{
Name: "Postgres",
Type: POSTGRES,
ConnectionInfo: ConnectionInfo{
Postgres: &PostgresConnectionInfo{
Host: "localhost",
Port: 333,
Username: "sdlfj",
Password: "sdfs",
DBName: "sdfsd",
},
},
},
{
Name: "Mysql",
Type: MYSQL,
ConnectionInfo: ConnectionInfo{
Mysql: &MySQLConnectionInfo{
Host: "localhost",
Port: 333,
Username: "sdlfj",
Password: "sdfs",
DBName: "sdfsd",
},
},
},
}
err := db.Create(&ds).Error
if err != nil {
log.Println("failed to create data")
}
}
func fetchData1(db *gorm.DB) {
var dsList []DataSource
if err := db.Find(&dsList).Error; err != nil {
log.Println("failed to load data")
}
log.Println(dsList)
}
关于go - 如何在 Gorm 中模仿联合类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74549098/