英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论