英文:
Allow pointer or value as argument in method
问题
我想要能够限制与Auth
相关联的类型,同时允许将指针或值作为参数传递给Marshal
方法中的val
。Unmarshal
需要一个指针,但是Marshal
可以是指针或值,而不影响功能(所有不必要的代码已被删除)。这种情况是否可行?
原因是我希望能够调用Marshal
并传递一个基本类型,例如字符串,而不必获取其指针。
我希望能够这样做:
a := &Auth{}
a.Marshal("val")
当前的实现方式:
a := &Auth{}
s := "val"
a.Marshal(&s)
注释:
使用Marshal(val A)
将无法正常工作。
例如:
a := Auth[string]
a.Marshal("val") // 只有在Unmarshal使用*A时才有效
type temp struct {}
b := Auth[*temp]
b.Marshal(&temp{})
out := new(temp)
b.Unmarshal(data, &out) // 这是我最初提出的问题,但现在出现在unmarshal中
英文:
I would like to be able to restrict the type tied to Auth
while allowing for either a pointer or value to be passed as an argument, namely val, for the Marshal
method. The Unmarshal requires a pointer, but the Marshal can be either a pointer or value without affecting functionality (all unnecessary code was removed). Is this possible?
type Auth[A any] struct {
// ...
}
func (a *Auth[A]) Unmarshal(b []byte, val *A) error {
// ...
if err := json.Unmarshal(b, val); err != nil {
return err
}
return nil
}
func (a *Auth[A]) Marshal(val *A) ([]byte, error) {
b, err := json.Marshal(src)
if err != nil {
return nil, err
}
// ...
return b, nil
}
Reasoning why I would like to be able to do this: I would like to be able to call Marshal
with a basic type, eg. a string, without having to get a pointer to it.
What I would like to be able to do:
a := &Auth{}
a.Marshal("val")
Current implementation:
a := &Auth{}
s := "val"
a.Marshal(&s)
Comments:
Using Marshal(val A)
will not work.
Eg.
a := Auth[string]
a.Marshal("val") // works, but only if Unmarshal uses *A
type temp struct {}
b := Auth[*temp]
b.Marshal(&temp{})
out := new(temp)
b.Unmarshal(data, &out) // this is the issue that I first presented, but now in the unmarshal
答案1
得分: 1
如果我理解你想要实现的内容,你需要进行两个小的更改:
- 对一个
A
值进行操作,而不是*A
。 - 从
Unmarshal()
返回一个新的A
,而不是接受一个*A
参数。
即:
type Auth[A any] struct{}
func (a *Auth[A]) Unmarshal(b []byte) (A, error) {
result := new(A)
err := json.Unmarshal(b, result)
return *result, err
}
func (a *Auth[A]) Marshal(val A) ([]byte, error) {
return json.Marshal(val)
}
在使用时,使用一个string
类型的参数和一个*Foo
类型的参数(为了清晰起见,省略了错误处理):
type Foo struct {
S string
}
func main() {
va := Auth[string]{}
pa := Auth[*Foo]{}
// Marshal a value type and a pointer to a Foo
mv, _ := va.Marshal("string")
mp, _ := pa.Marshal(&Foo{"bar"})
// Emit the marshalled []bytes
fmt.Printf("%s\n", mv)
fmt.Printf("%s\n", mp)
// Unmarshal from the marshalled []byte for
// both the value and the pointer
v, _ := va.Unmarshal(mv)
p, _ := pa.Unmarshal(mp)
// Emit the unmarshalled results and their type
fmt.Printf("%s %[1]T\n", v)
fmt.Printf("%s %[1]T\n", p)
}
英文:
If I understand what you are trying to achieve you need to make 2 small changes:
- operate on an
A
value, not*A
- return a new
A
fromUnmarshal()
rather than accepting a*A
arg
i.e.:
type Auth[A any] struct{}
func (a *Auth[A]) Unmarshal(b []byte) (A, error) {
result := new(A)
err := json.Unmarshal(b, result)
return *result, err
}
func (a *Auth[A]) Marshal(val A) ([]byte, error) {
return json.Marshal(val)
}
In use, using a string
type argument and a *Foo
type argument (where Foo
is a struct type) (error handling omitted for clarity):
type Foo struct {
S string
}
func main() {
va := Auth[string]{}
pa := Auth[*Foo]{}
// Marshal a value type and a pointer to a Foo
mv, _ := va.Marshal("string")
mp, _ := pa.Marshal(&Foo{"bar"})
// Emit the marshalled []bytes
fmt.Printf("%s\n", mv)
fmt.Printf("%s\n", mp)
// Unmarshal from the marshalled []byte for
// both the value and the pointer
v, _ := va.Unmarshal(mv)
p, _ := pa.Unmarshal(mp)
// Emit the unmarshalled results and their type
fmt.Printf("%s %[1]T\n", v)
fmt.Printf("%s %[1]T\n", p)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论