如何为结构指针上的方法定义接口

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

How to define interface for methods on struct pointer

问题

对于struct,可以定义一个可以更新struct变量的func。有没有办法在interface中使用这些函数?

在下面的代码中,我试图创建一个最小的示例来描述我的问题。定义了RectCircle两个struct。这两个struct都有PerimeterExpand函数。
Perimeter函数计算形状的周长。Expand函数通过更改其属性来增加形状的周长。还定义了具有Perimeter方法签名的Shape接口。

viewShapeData函数接受Shape类型的输入参数。该函数查看形状的数据,并运行Perimeter方法并查看形状的周长。

package main

import "fmt"

type Shape interface {
	Perimeter() float64
}

type Rect struct {
	width  float64
	height float64
}

type Circle struct {
	radius float64
}

func (s Rect) Perimeter() float64 {
	return 2 * (s.width + s.height)
}

func (s Circle) Perimeter() float64 {
	return 2 * 3.14 * s.radius
}

func (s *Rect) Expand(increaseValue float64) {
	s.width += increaseValue / 2
}

func (s *Circle) Expand(increaseValue float64) {
	s.radius += increaseValue / 3.14 / 2
}

func main() {
	a := Circle{radius: 10.0}
	b := Rect{width: 2.4, height: 5}

	a.Expand(1)
	viewShapeData(a)

	b.Expand(1)
	viewShapeData(b)
}

func viewShapeData(s Shape) {
	fmt.Printf("value: %v, Type: %T, Perimeter: %f\n", s, s, s.Perimeter())
}

现在我正在寻找一种在viewShapeData函数中调用Expand方法的方法。我尝试了不同的方法,并对上述代码进行了以下更改:

type Shape interface {
	Perimeter() float64
	Expand(float64)
}

func main() {
	a := Circle{radius: 10.0}
	b := Rect{width: 2.4, height: 5}

	viewShapeData(a)
	viewShapeData(b)
}

func viewShapeData(s Shape) {
	s.Expand(1)
	fmt.Printf("value: %v, Type: %T, Perimeter: %f\n", s, s, s.Perimeter())
}

但是出现了以下错误:

cannot use a (type Circle) as type Shape in argument to viewShapeData:
        Circle does not implement Shape (Expand method has pointer receiver)
cannot use b (type Rect) as type Shape in argument to viewShapeData:
        Rect does not implement Shape (Expand method has pointer receiver)

请给我一个解决方案,或告诉我为什么Golang不支持这种编码方式。

英文:

For structs, it is possible to define a func that can update struct variables. Is there any way to use those functions in interface?

In the following code, I tried to create a minimal example to describe my question. two struct of Rect and Circle are defined. Both of the structs have Perimeter and Expand functions.
Perimeter function calculates the perimeter of the shape. Expand function increases the perimeter of the shape by changing its properties. Also Shape interface with the Perimeter method signature is defined.

viewShapeData function accept input parameter of Shape type. This function view data of the shapes and also run the Perimeter method and view the perimeter of shapes.

package main

import "fmt"

type Shape interface {
	Perimeter() float64
}

type Rect struct {
	width  float64
	height float64
}

type Circle struct {
	radius float64
}

func (s Rect) Perimeter() float64 {
	return 2 * (s.width + s.height)
}

func (s Circle) Perimeter() float64 {
	return 2 * 3.14 * s.radius
}

func (s *Rect) Expand(increaseValue float64) {
	s.width += increaseValue / 2
}

func (s *Circle) Expand(increaseValue float64) {
	s.radius += increaseValue / 3.14 / 2
}

func main() {
	a := Circle{radius: 10.0}
	b := Rect{width: 2.4, height: 5}

	a.Expand(1)
	viewShapeData(a)

	b.Expand(1)
	viewShapeData(b)
}

func viewShapeData(s Shape) {
	fmt.Printf("value: %v, Type: %T, Perimeter: %f\n", s, s, s.Perimeter())
}

Now I'm looking for a way to call the Expand method in the viewShapeData function. I tried different ways and applied the following changes in the described code:

type Shape interface {
	Perimeter() float64
	Expand(float64)
}

func main() {
	a := Circle{radius: 10.0}
	b := Rect{width: 2.4, height: 5}

	viewShapeData(a)
	viewShapeData(b)
}

func viewShapeData(s Shape) {
	s.Expand(1)
	fmt.Printf("value: %v, Type: %T, Perimeter: %f\n", s, s, s.Perimeter())
}

But these errors appear:

cannot use a (type Circle) as type Shape in argument to viewShapeData:
        Circle does not implement Shape (Expand method has pointer receiver)
cannot use b (type Rect) as type Shape in argument to viewShapeData:
        Rect does not implement Shape (Expand method has pointer receiver)

Please give me a solution or tell me why Golang does not support this kind of coding.

答案1

得分: 1

所以,如果你想使用指针接收器(pointer receiver),你也应该将指针传递给接受接口的函数。

例如:

func main() {
    a := Circle{radius: 10.0}
    b := Rect{width: 2.4, height: 5}

    a.Expand(1)
    viewShapeData(&a)

    b.Expand(1)
    viewShapeData(&b)
}

https://play.golang.com/p/pmHd5yl_v8p

英文:

So, if you want to use a pointer receiver, you also should pass a pointer into the function that takes the interface.

For example

func main() {
	a := Circle{radius: 10.0}
	b := Rect{width: 2.4, height: 5}
    
    a.Expand(1)
	viewShapeData(&a)

    b.Expand(1)
	viewShapeData(&b)
}

https://play.golang.com/p/pmHd5yl_v8p

huangapple
  • 本文由 发表于 2021年12月27日 18:31:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/70494316.html
匿名

发表评论

匿名网友

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

确定