指针接收器和值接收器在使用Iris框架实现时的区别

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

Pointer receiver and Value receiver difference in implementation with Iris framework

问题

我最近在学习Iris框架。在实现Handler时遇到了一个问题,就像下面的代码一样:

package controller

import "github.com/kataras/iris"

type Pages struct{
}

func (p *Pages) Serve(c *iris.Context) {
}

为了使用这个控制器,我实现了以下入口脚本:

package main

import (
     "github.com/kataras/iris"
     "web/controller"
)

func main(){
      ctrl := controller.Pages{}
      iris.Handle("GET", "/", ctrl)
      iris.Listen(":8080")
}

但是当我编译代码时,我得到了以下错误信息:

cannot use ctrl (type controllers.Pages) as type iris.Handler in argument to iris.Handle:
	controllers.Pages does not implement iris.Handler (Serve method has pointer receiver)

在我将声明更改为以下内容之后:

ctrl := &controller.Pages{}

然后编译器通过了,没有任何投诉。

问题是:我认为以下语句是相等的,因为GO编译器会在幕后进行转换:

type Pages struct {
}

func (p *Pages) goWithPointer() {
    fmt.Println("goWithPointer")
}

func (p Pages) goWithValue() {
    fmt.Println("goWithValue")
}

func main() {
    p1 := Pages{}
    p2 := &Pages{}

    p1.goWithPointer()
    p1.goWithValue()

    p2.goWithPointer()
    p2.goWithValue()
}

为什么我不能使用ctrl := controller.Pages{}作为iris.Handle()的参数,而要使用ctrl := &controller.Pages{}作为iris.Handle()的参数?

谢谢你的时间和分享。

英文:

I am studying Iris framework recently. I encountered a question when I was implementing the Handler. Like following:

<!-- language: lang-golang -->

package controller

import &quot;github.com/kataras/iris&quot;    

type Pages struct{
}

func (p *Pages) Serve(c *iris.Context) {
}

In order to use this controller, I implemented the following entry script:

<!-- language: lang-golang -->

package main

import (
     &quot;github.com/kataras/iris&quot;
     &quot;web/controller&quot;
)

func main(){
      ctrl := controller.Pages{}
      iris.Handle(&quot;GET&quot;, &quot;/&quot;, ctrl)
      iris.Listen(&quot;:8080&quot;)
}

But when I compiled the code, I got the following error message:

cannot use ctrl (type controllers.Pages) as type iris.Handler in argument to iris.Handle:
	controllers.Pages does not implement iris.Handler (Serve method has pointer receiver)

After I changed the declaration to:

ctrl := &amp;controller.Pages{}

Then the compiler passed with no complaint.

The question is: I thought the following statements are equal, since the GO compiler will do the conversion under the table:

<!-- language: lang-golang -->

type Pages struct {
}

func (p *Pages) goWithPointer() {
    fmt.Println(&quot;goWithPointer&quot;)
}

func (p Pages) goWithValue() {
    fmt.Println(&quot;goWithValue&quot;)
}

func main() {
    p1 := Pages{}
    p2 := &amp;Pages{}

    p1.goWithPointer()
    p1.goWithValue()

    p2.goWithPointer()
    p2.goWithValue()
}

Why can't I use ctrl := controller.Pages{} as the parameter to iris.Handle(), instead of ctrl := &amp;controller.Pages{} as the parameter to iris.Handle()?

Thank you for your time and sharing.

答案1

得分: 2

查看文档:

> 一个类型可以有一个与之关联的方法集。接口类型的方法集就是它的接口。任何其他类型 T 的方法集由所有声明了接收器类型为 T 的方法组成。相应指针类型 *T 的方法集是所有声明了接收器为 *TT 的方法的集合(也就是说,它还包含了 T 的方法集)。对于包含匿名字段的结构体,还有其他规则,详见结构体类型的章节。其他任何类型都有一个空的方法集。在方法集中,每个方法必须有一个唯一的非空方法名。

并参见:https://stackoverflow.com/a/33591156/6169399:

> 如果你有一个接口 I,并且 I 的方法集中的一些或全部方法是由具有接收器为 *T 的方法提供的(其余方法由具有接收器为 T 的方法提供),那么 *T 满足接口 I,但 T 不满足。这是因为 *T 的方法集包括 T 的方法集,但反过来不成立。

使用 ctrl := Pages{} 会出错:

cannot use ctrl (type Pages) as type Handler in argument to Handle:
Pages does not implement Handler (Serve method has pointer receiver)

使用 ctrl := Pages{} 需要:

func (p Pages) Serve() {
    fmt.Println(p.i)
}

Iris Handler 是一个接口类型。像这个工作示例一样(见注释):

<!-- language: lang-golang -->

package main

import &quot;fmt&quot;

type Handler interface {
	Serve()
}

type Pages struct {
	i int
}

func (p *Pages) Serve() {
	fmt.Println(p.i)
}

func Handle(p Handler) {
	p.Serve()
}

func main() {
	// cannot use ctrl (type Pages) as type Handler in argument to Handle:
	// Pages does not implement Handler (Serve method has pointer receiver)
	//ctrl := Pages{}
	ctrl := &amp;Pages{101}
	Handle(ctrl)
}

输出:

101
英文:

See Docs:

> A type may have a method set associated with it. The method set of an
> interface type is its interface. The method set of any other type T
> consists of all methods declared with receiver type T. The method set
> of the corresponding pointer type *T is the set of all methods
> declared with receiver *T or T (that is, it also contains the method
> set of T). Further rules apply to structs containing anonymous fields,
> as described in the section on struct types. Any other type has an
> empty method set. In a method set, each method must have a unique
> non-blank method name.

And see: https://stackoverflow.com/a/33591156/6169399 :

> If you have an interface I, and some or all of the methods in I's
> method set are provided by methods with a receiver of *T (with the
> remainder being provided by methods with a receiver of T), then *T
> satisfies the interface I, but T doesn't. That is because *T's method
> set includes T's, but not the other way around.

Using ctrl := Pages{} makes error:

cannot use ctrl (type Pages) as type Handler in argument to Handle:
Pages does not implement Handler (Serve method has pointer receiver)

Using ctrl := Pages{}needs:

func (p Pages) Serve() {
    fmt.Println(p.i)
}

Iris Handler is an interface type. like this working sample (see comment):

<!-- language: lang-golang -->

package main

import &quot;fmt&quot;

type Handler interface {
	Serve()
}

type Pages struct {
	i int
}

func (p *Pages) Serve() {
	fmt.Println(p.i)
}

func Handle(p Handler) {
	p.Serve()
}

func main() {
	// cannot use ctrl (type Pages) as type Handler in argument to Handle:
	// Pages does not implement Handler (Serve method has pointer receiver)
	//ctrl := Pages{}
	ctrl := &amp;Pages{101}
	Handle(ctrl)
}

output:

101

答案2

得分: 0

根据https://godoc.org/github.com/kataras/iris#Handler,Iris Handler是一个接口类型。

Go只对变量进行隐式指针转换,而不对接口进行转换。

英文:

According to https://godoc.org/github.com/kataras/iris#Handler. Iris Handler is an interface type.

GO performs implicit pointer-conversion on variables only, not on interfaces.

huangapple
  • 本文由 发表于 2016年8月17日 10:57:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/38987391.html
匿名

发表评论

匿名网友

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

确定