实现接口的函数与实现接口的结构体之间的区别。

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

Function Implementing Interface vs. Struct Implementing Interface

问题

在Go语言中,当实现一个只有一个方法的接口时,何时应该使用函数而不是结构体呢?

假设有一个具有单个方法的日志接口:

type Logger interface {
	Log(message string)
}

选项1:使用结构体:

package main

import (
	"fmt"
)

type Controller struct {
	l Logger
}

func (c Controller) Run() {
	c.l.Log("done")
}

type Logger interface {
	Log(message string)
}

// 空结构体实现接口的方法
type LoggerImpl struct{}

func (li LoggerImpl) Log(message string) {
	fmt.Println(message)
}

func main() {
	l := LoggerImpl{}
	c := Controller{l: l}
	c.Run()
}

选项2:使用函数

package main

import (
	"fmt"
)

type Controller struct {
	l Logger
}

func (c Controller) Run() {
	c.l.Log("done")
}

type Logger interface {
	Log(message string)
}

type LoggerAdapter func(message string)

func (lg LoggerAdapter) Log(message string) {
	lg(message)
}

func LogOutput(message string) {
	fmt.Println(message)
}

func main() {
	l := LoggerAdapter(LogOutput)
	c := Controller{l: l}
	c.Run()
}

两种方法都可以工作,但似乎函数选项对变化的适应性较差。

是否有使用函数来实现接口的示例,比使用结构体更好?或者,在某些情况下使用结构体选项存在哪些缺点?

英文:

When implementing an interface with a single method in Go, when should a function be used vs. a struct?

Contrived example: Say I have a logging interface with a single method:

type Logger interface {
	Log(message string)
}

Option 1: Use a Struct:

package main

import (
	"fmt"
)

type Controller struct {
	l     Logger
}
func (c Controller) Run() {
	c.l.Log("done")
}

type Logger interface {
	Log(message string)
}

// Empty struct with method implementing the interface
type LoggerImpl struct {}
func (li LoggerImpl) Log(message string) {
	fmt.Println(message)
}

func main() {
	l := LoggerImpl{}
	c := Controller{l: l}
	c.Run()
}

Option #2 - Use a Function

package main

import (
	"fmt"
)

type Controller struct {
	l     Logger
}
func (c Controller) Run() {
	c.l.Log("done")
}

type Logger interface {
	Log(message string)
}

type LoggerAdapter func(message string)

func (lg LoggerAdapter) Log(message string) {
	lg(message)
}

func LogOutput(message string) {
	fmt.Println(message)
}

func main() {
	l := LoggerAdapter(LogOutput)
	c := Controller{l: l}
	c.Run()
}

Both work, but it seems like the function option is less resilient to change?

Is there an example of where using a function to implement an interface is a much better idea than using a struct? Or perhaps, downsides to using the struct option in certain scenarios?

答案1

得分: 1

你可以在net/http中使用HandlerHandlerFunc来实现这一点。满足接口的函数很方便-你甚至可以传递一个闭包:

c := Controller{
    l: LoggerAdapter(func(message string) {fmt.Println(message)}),
}

但是函数不能有字段,而且它通常不会有额外有用的方法。像这样的函数类型往往只有一个方法,该方法只是调用函数。

如果你需要一个更复杂的类型,那就是结构体,你可以使用它。

英文:

You see this in net/http with Handler and HandlerFunc. A function that satisfies an interface is convenient - you can pass in a closure even:

c := Controller{
    l: LoggerAdapter(func(message string) {fmt.Println(message)}),
}

But a function can't have fields and it's unusual for it to have additional useful methods. Func types like this tend to have a single method that just calls the function.

If you need a more complex type, that's what a struct is, so you can use that.

huangapple
  • 本文由 发表于 2023年4月20日 02:45:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76057887.html
匿名

发表评论

匿名网友

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

确定