英文:
How can non-struct type extends struct functions
问题
更新:好的,我弄错了。CustomJSONType的函数不能访问它所嵌入的结构体的字段,因此User和IntList都应该定义自己的Scan和Value,或者尝试其他解决方法。
原始帖子于2021年6月21日发布
我正在使用GORM,并尝试定义一些自定义类型,如User和IntList。
type User struct {
Id int
Name string
Email string
}
type IntList []int
众所周知,GORM自定义类型必须实现Value和Scan函数。这是我所做的-我定义了一个CustomJSONType,它实现了以下的Value和Scan函数:
type CustomJSONType struct {}
func (t *CustomJSONType) Scan(src interface{}) error {
bytes, ok := src.([]byte)
if !ok {
return errors.New("无效的输入类型")
}
err := json.Unmarshal(bytes, t)
if err != nil{
return err
}
return nil
}
func (t CustomJSONType) Value() (driver.Value, error) {
bytes, err := json.Marshal(t)
if err != nil {
return []byte{}, err
}
return bytes, err
}
func (t CustomJSONType) GormDataType() string {
return "json"
}
要为User添加Value和Scan,我只需要在User的定义中添加一行代码:
更新:由于CustomJSONType无法访问User的字段,这不起作用
type User struct {
CustomJSONType
Id int
Name string
Email string
}
然而,我不知道如何将IntList扩展为CustomJSONType。我必须显式地为IntList定义Scan和Value。即使在最好的情况下,我可以将Value和Scan的实现包装为独立的函数,但仍然必须在IntList中编写Scan和Value的签名。有没有建议可以像User一样简单地定义IntList?
英文:
update: Ok I made it wrong. CustomJSONType's functions can not access the fields of the struct that it is embedded into, for which both User and IntList should define Scan and Value of their own or try other workarounds.
original post on 2021-6-21
I am using GORM and trying to define some custom types like User and IntList.
type User struct {
Id int
Name string
Email string
}
type IntList []int
And as is known GORM custom type must implement Value and Scan functions. Here's what I did - I defined a CustomJSONType which implements Value and Scan like this:
type CustomJSONType struct {}
func (t *CustomJSONType) Scan(src interface{}) error {
bytes, ok := src.([]byte)
if !ok {
return errors.New("invalid input type")
}
err := json.Unmarshal(bytes, t)
if err != nil{
return err
}
return nil
}
func (t CustomJSONType) Value() (driver.Value, error) {
bytes, err := json.Marshal(t)
if err != nil {
return []byte{}, err
}
return bytes, err
}
func (t CustomJSONType) GormDataType() string {
return "json"
}
To equip User with Value and Scan, all I have to do is to add a single line to the definition of User:
update: it won't work as CustomJSONType can't access fields of User
type User struct {
CustomJSONType
Id int
Name string
Email string
}
However, I have no idea how to extend IntList with CustomJSONType. I have to explicitly define Scan and Value for IntList. Even at best I can wrap the implementation of Value and Scan as independent functions but still have to write signatures for Scan and Value in IntList. Any suggestions to define IntList just as simple as User?
答案1
得分: 1
在golang中,没有"继承"的概念,只有组合。与普通的面向对象编程语言不同,结构体CustomJSONType无法访问IntList和User中的数据,因此方法CustomJSONType.Value无法序列化除自身以外的其他类型。如果你想要实现一种方法,并在任何地方使用它,我提供以下思路。
package main
import (
"database/sql/driver"
"encoding/json"
"errors"
"fmt"
)
type CustomJSONType struct {
data interface{}
}
func (t *CustomJSONType) Scan(src interface{}) error {
bytes, ok := src.([]byte)
if !ok {
return errors.New("无效的输入类型")
}
err := json.Unmarshal(bytes, t.data)
if err != nil{
return err
}
return nil
}
func (t CustomJSONType) Value() (driver.Value, error) {
bytes, err := json.Marshal(t.data)
if err != nil {
return []byte{}, err
}
return bytes, err
}
func (t CustomJSONType) GormDataType() string {
return "json"
}
type User struct {
Id int
Name string
Email string
}
type Project struct {
user CustomJSONType
}
func (p *Project) SetUser(u User) {
p.user.data = u
}
func (p *Project) GetUser() User {
user := p.user.data.(User)
return user
}
英文:
There is no "inherit" concept in golang but only combination. Don't like normal OOP language, the struct CustomJSONType can't access the data from IntList and User, so the method CustomJSONType.Value can't serialize other types than itself. If you want implement a method once and use it anywhere, I provide an idea bellow.
package main
import (
"database/sql/driver"
"encoding/json"
"errors"
"fmt"
)
type CustomJSONType struct {
data interface{}
}
func (t *CustomJSONType) Scan(src interface{}) error {
bytes, ok := src.([]byte)
if !ok {
return errors.New("invalid input type")
}
err := json.Unmarshal(bytes, t.data)
if err != nil{
return err
}
return nil
}
func (t CustomJSONType) Value() (driver.Value, error) {
bytes, err := json.Marshal(t.data)
if err != nil {
return []byte{}, err
}
return bytes, err
}
func (t CustomJSONType) GormDataType() string {
return "json"
}
type User struct {
Id int
Name string
Email string
}
type Project struct {
user CustomJSONType
}
func (p *Project) SetUser(u User) {
p.user.data = u
}
func (p *Project) GetUser() User {
user := p.user.data.(User)
return user
}
答案2
得分: 1
不确定我是否正确理解了你的问题。但是你可以组合多种类型,包括整数数组,而无需创建结构体。它们仍然是一种类型,并且可以在函数中使用。但是组合类型需要使用结构体,这就是为什么你不能直接使用数组索引的原因。
你可以在这里看到代码示例:
https://play.golang.org/p/MF5eMcgmeak
英文:
Not sure if I understood you correctly. But you can combine several types, including an array of ints, without creating a structure. They remain a type and are available in functions. But combining types requires a structure, which is why you cannot directly use array addressing.
type IntArr []int
type AnyStruct struct{
Uses bool
}
type TestIntArrStruct struct{
IntArr
AnyStruct
}
func(arr *IntArr) Add(i ...int){
*arr = append(*arr, i...)
}
func(anyStruct *AnyStruct) Invert(){
anyStruct.Uses = !anyStruct.Uses
}
var a TestIntArrStruct
a.Add(1,2,3)
a.Invert()
You can see it here:
https://play.golang.org/p/MF5eMcgmeak
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论