接口类型返回

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

Interface type return

问题

当返回类型是接口时,在声明地址(&)和不声明地址之间有什么区别?

func NewService(rep repository.Repository) Service {
    // 或者不使用 "&"
    return &myService{
        repository: rep
    }   
}

在这段代码中,如果返回类型是接口类型,使用&符号表示返回一个指向结构体的指针,而不使用&符号则表示返回一个结构体的值。这两种方式的区别在于返回的对象的类型。如果返回类型是接口类型,使用&符号可以返回一个指向实现该接口的结构体的指针,而不使用&符号则返回一个实现该接口的结构体的值。

英文:

What is the difference between declare the address (&) or not once the return type is an interface?

func NewService(rep repository.Repository) Service {
    // or without the "&"
    return &myService{
        repository: rep
    }   
}

答案1

得分: 1

差异在于,如果需要实现接口的方法具有指针接收器,那么必须返回一个指针。如果方法具有值接收器,可以使用任何一种。例如:

package main

import (
    "fmt"
)

type Hello interface {
    Hello() string
}

type World interface {
    World() string
}

type HelloWorlder interface {
    Hello() string
    World() string
}

type test struct{}

func (t *test) Hello() string {
    return "Hello"
}

func (t test) World() string {
    return "World"
}

func HelloWorld1() HelloWorlder {
    return &test{}
}

// 如果取消注释,它将无法编译
//func HelloWorld2() HelloWorlder {
//    return test{}
//}

func main() {
    greeter1 := HelloWorld1()
    //greeter2 := HelloWorld2()
    fmt.Println(greeter1.Hello(), greeter1.World())
    //fmt.Println(greeter2.Hello(), greeter2.World())
}

链接:https://play.golang.org/p/ToGKyIjIJNQ

英文:

The difference is that if a method needed to implement the interface has a pointer receiver, you must return a pointer. If the method instead has a value receiver, you can use either. For example:

https://play.golang.org/p/ToGKyIjIJNQ

package main

import (
  "fmt"
)

type Hello interface {
  Hello() string
}

type World interface {
  World() string
}

type HelloWorlder interface {
  Hello() string
  World() string
}

type test struct{}

func (t *test) Hello() string {
  return "Hello"
}

func (t test) World() string {
  return "World"
}

func HelloWorld1() HelloWorlder {
  return &test{}
}

// if you uncomment this, it won't compile
//func HelloWorld2() HelloWorlder {
//    return test{}
//}

func main() {
  greeter1 := HelloWorld1()
  //greeter2 := HelloWorld2()
  fmt.Println(greeter1.Hello(), greeter1.World())
  //fmt.Println(greeter2.Hello(), greeter2.World())
}

答案2

得分: 0

这个问题归结为接口的可赋值性。

https://golang.org/ref/spec#Assignability

> 如果满足以下条件之一,值x可以赋值给类型为T的变量("x is assignable to T"):...
> - T是一个接口类型,并且x实现了T。...

https://golang.org/ref/spec#Interface_types

> 接口类型指定了一个称为其接口的方法集。

https://golang.org/ref/spec#Method_sets

> 类型T的方法集包括所有声明了接收器类型为T的方法。相应指针类型T的方法集是所有声明了接收器类型为T或T的方法的集合(也就是说,它还包含了T的方法集)。
>
> 类型的方法集确定了该类型实现的接口以及可以使用该类型的接收器调用的方法。

> 当返回类型是接口时,声明地址(&)和不声明地址有什么区别?

会导致构建错误。

Effective Go中有一章讲述了指针接收器和值接收器之间的区别。

https://golang.org/doc/effective_go#methods

英文:

this question boils down to assignability of an interface.

https://golang.org/ref/spec#Assignability

> A value x is assignable to a variable of type T ("x is assignable to
> T") if one of the following conditions applies: ...
> - T is an interface type and x implements T. ...

https://golang.org/ref/spec#Interface_types

> An interface type specifies a method set called its interface.

https://golang.org/ref/spec#Method_sets

> The method set of a 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)
>
> The method set of a type determines the interfaces that the type implements and the methods that can be called using a receiver of that type.

> What is the difference between declare the address (&) or not once the return type is an interface?

A build error.

The Effective Go has a chapter about the differences between pointer and value receivers.

https://golang.org/doc/effective_go#methods

huangapple
  • 本文由 发表于 2021年9月15日 00:40:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/69181571.html
匿名

发表评论

匿名网友

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

确定