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

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

Allow pointer or value as argument in method

问题

我想要能够限制与Auth相关联的类型,同时允许将指针或值作为参数传递给Marshal方法中的valUnmarshal需要一个指针,但是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

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

  1. 对一个A值进行操作,而不是*A
  2. 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:

  1. operate on an A value, not *A
  2. return a new A from Unmarshal() 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)
}

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:

确定