允许在方法中使用指针或值作为参数。

huangapple go评论110阅读模式
英文:

Allow pointer or value as argument in method

问题

我想要能够限制与Auth相关联的类型,同时允许将指针或值作为参数传递给Marshal方法中的valUnmarshal需要一个指针,但是Marshal可以是指针或值,而不影响功能(所有不必要的代码已被删除)。这种情况是否可行?

原因是我希望能够调用Marshal并传递一个基本类型,例如字符串,而不必获取其指针。

我希望能够这样做:

  1. a := &Auth{}
  2. a.Marshal("val")

当前的实现方式:

  1. a := &Auth{}
  2. s := "val"
  3. a.Marshal(&s)

注释:
使用Marshal(val A)将无法正常工作。
例如:

  1. a := Auth[string]
  2. a.Marshal("val") // 只有在Unmarshal使用*A时才有效
  3. type temp struct {}
  4. b := Auth[*temp]
  5. b.Marshal(&temp{})
  6. out := new(temp)
  7. 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?

  1. type Auth[A any] struct {
  2. // ...
  3. }
  4. func (a *Auth[A]) Unmarshal(b []byte, val *A) error {
  5. // ...
  6. if err := json.Unmarshal(b, val); err != nil {
  7. return err
  8. }
  9. return nil
  10. }
  11. func (a *Auth[A]) Marshal(val *A) ([]byte, error) {
  12. b, err := json.Marshal(src)
  13. if err != nil {
  14. return nil, err
  15. }
  16. // ...
  17. return b, nil
  18. }

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:

  1. a := &Auth{}
  2. a.Marshal("val")

Current implementation:

  1. a := &Auth{}
  2. s := "val"
  3. a.Marshal(&s)

Comments:
Using Marshal(val A) will not work.
Eg.

  1. a := Auth[string]
  2. a.Marshal("val") // works, but only if Unmarshal uses *A
  3. type temp struct {}
  4. b := Auth[*temp]
  5. b.Marshal(&temp{})
  6. out := new(temp)
  7. b.Unmarshal(data, &out) // this is the issue that I first presented, but now in the unmarshal

答案1

得分: 1

如果我理解你想要实现的内容,你需要进行两个小的更改:

  1. 对一个A值进行操作,而不是*A
  2. Unmarshal()返回一个新的A,而不是接受一个*A参数。

即:

  1. type Auth[A any] struct{}
  2. func (a *Auth[A]) Unmarshal(b []byte) (A, error) {
  3. result := new(A)
  4. err := json.Unmarshal(b, result)
  5. return *result, err
  6. }
  7. func (a *Auth[A]) Marshal(val A) ([]byte, error) {
  8. return json.Marshal(val)
  9. }

在使用时,使用一个string类型的参数和一个*Foo类型的参数(为了清晰起见,省略了错误处理):

  1. type Foo struct {
  2. S string
  3. }
  4. func main() {
  5. va := Auth[string]{}
  6. pa := Auth[*Foo]{}
  7. // Marshal a value type and a pointer to a Foo
  8. mv, _ := va.Marshal("string")
  9. mp, _ := pa.Marshal(&Foo{"bar"})
  10. // Emit the marshalled []bytes
  11. fmt.Printf("%s\n", mv)
  12. fmt.Printf("%s\n", mp)
  13. // Unmarshal from the marshalled []byte for
  14. // both the value and the pointer
  15. v, _ := va.Unmarshal(mv)
  16. p, _ := pa.Unmarshal(mp)
  17. // Emit the unmarshalled results and their type
  18. fmt.Printf("%s %[1]T\n", v)
  19. fmt.Printf("%s %[1]T\n", p)
  20. }
英文:

If I understand what you are trying to achieve you need to make 2 small changes:

  1. operate on an A value, not *A
  2. return a new A from Unmarshal() rather than accepting a *A arg

i.e.:

  1. type Auth[A any] struct{}
  2. func (a *Auth[A]) Unmarshal(b []byte) (A, error) {
  3. result := new(A)
  4. err := json.Unmarshal(b, result)
  5. return *result, err
  6. }
  7. func (a *Auth[A]) Marshal(val A) ([]byte, error) {
  8. return json.Marshal(val)
  9. }

In use, using a string type argument and a *Foo type argument (where Foo is a struct type) (error handling omitted for clarity):

  1. type Foo struct {
  2. S string
  3. }
  4. func main() {
  5. va := Auth[string]{}
  6. pa := Auth[*Foo]{}
  7. // Marshal a value type and a pointer to a Foo
  8. mv, _ := va.Marshal("string")
  9. mp, _ := pa.Marshal(&Foo{"bar"})
  10. // Emit the marshalled []bytes
  11. fmt.Printf("%s\n", mv)
  12. fmt.Printf("%s\n", mp)
  13. // Unmarshal from the marshalled []byte for
  14. // both the value and the pointer
  15. v, _ := va.Unmarshal(mv)
  16. p, _ := pa.Unmarshal(mp)
  17. // Emit the unmarshalled results and their type
  18. fmt.Printf("%s %[1]T\n", v)
  19. fmt.Printf("%s %[1]T\n", p)
  20. }

huangapple
  • 本文由 发表于 2023年4月11日 00:39:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/75978909.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定