Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go中的装饰函数_Go_Design Patterns_Decorator_Demo - Fatal编程技术网

Go中的装饰函数

Go中的装饰函数,go,design-patterns,decorator,demo,Go,Design Patterns,Decorator,Demo,装饰器模式(函数)具有: 当一个方法有许多正交关注点时,它是非常有用的。。。也就是说,这些关注点都不相关,只是我们希望在调用方法时执行所有(或部分)关注点。这就是decorator模式真正有帮助的地方 通过实现decorator模式,我们订阅了开闭主体。我们的方法对将来的扩展是开放的,但对将来的修改是封闭的。遵守开闭原则有很多好处 然而,我发现的所有示例都非常复杂(例如,使用许多中间件编写HTTP服务器)。这使我很难在其他地方应用这一原则。我需要一些我可以很容易地试穿的东西,这样我的头就可以绕着

装饰器模式(函数)具有:

当一个方法有许多正交关注点时,它是非常有用的。。。也就是说,这些关注点都不相关,只是我们希望在调用方法时执行所有(或部分)关注点。这就是decorator模式真正有帮助的地方

通过实现decorator模式,我们订阅了开闭主体。我们的方法对将来的扩展是开放的,但对将来的修改是封闭的。遵守开闭原则有很多好处

然而,我发现的所有示例都非常复杂(例如,使用许多中间件编写HTTP服务器)。这使我很难在其他地方应用这一原则。我需要一些我可以很容易地试穿的东西,这样我的头就可以绕着它转了

有人能给我一个简单的例子,可以最好地说明如何做装饰模式(函数)在围棋请

,过于简单,无法投入实际使用。我需要一些能说明这一点的东西:

func Decorate(c Decorated, ds ...Decorator) Decorated {
    decorated := c
    for _, decorate := range ds {
        decorated = decorate(decorated)
    }
    return decorated
}

根据不同的选项/指令进行字符串操作,例如向上、向下、向base64等,在IMO中是最好的示例,并添加前缀/后缀,如“.

我知道一个非常好的装饰器/中间件示例,它使用了您演示的相同技术。虽然这不是特定于字符串操作,但我发现它的制作非常精美,如下所示(浏览代码):

查看
类型PublisherOption function(*publisherConfig)错误

您会注意到一些函数返回
PublisherOption
type。这些是装饰器/中间件

操作发生在
newkafkapulisher
函数上:

func NewKafkaPublisher(
  broker, topic string,
  options ...PublisherOption,
  ) (pubsub.Publisher, error) {
  if len(strings.Trim(broker, " \t")) == 0 {
      return nil, ErrNoBrokers
  }
  brokerHosts := strings.Split(broker, ",")

  if len(topic) == 0 {
      return nil, ErrNoTopic
  }
  // set sensible defaults
  pc := &publisherConfig{
    syncPublisher: defaultSyncPublisher,
    ackMode:       defaultRequiredAcks,
    successes:     nil,
    logger:        log.NewNopLogger(),
    topic:         topic,
    partitioner:   sarama.NewManualPartitioner(topic),
    partition:     0,
  }

 // parse optional parameters
 for _, option := range options {
     if err := option(pc); err != nil {
        return nil, err
     }
 }
注意,它循环通过
选项
,并调用每个装饰器/中间件

补充示例如下:

可运行代码:

希望有帮助:)

最好的例子是根据不同的选项/指令进行字符串操作,例如,到上限、到下限、添加前缀/后缀、到base64等等

这是您询问的示例:

package main

import (
    "fmt"
    "strings"
)

const (
    prefix = "PREFIX"
    suffix = "SUFFIX"
)

type Decorated=string

func addConstPrefix(s string) string {
    return prefix + s
}

func addConstSuffix(s string) string {
    return s + suffix
}

type Decorator=func(string) string

func Decorate(c Decorated, ds ...Decorator) Decorated {
    decorated := c
    for _, decorator := range ds {
        decorated = decorator(decorated)
    }
    return decorated
}

func main() {

    var toLower Decorator = strings.ToLower
    var toUpper Decorator = strings.ToUpper
    var dec3 Decorator = addConstPrefix
    var dec4 Decorator = addConstSuffix

    input := "Let's decorate me!"
    inputUppercase := Decorate(input, []Decorator{toUpper}...)
    fmt.Println(inputUppercase)

    allDecorators := []Decorator{toUpper, toLower, dec3, dec4}
    output := Decorate(input, allDecorators...)
    fmt.Println(output)
}
注意,为了简单起见,它使用Golang的类型别名,这是Go 1.9中引入的。以下是我们使用的两个别名:

type Decorated=string
type Decorator=func(string)string
以便以后可以应用您的
decoration()
函数。然后,我们只需创建几个与我们定义的类型签名匹配的装饰器(函数):

var toLower Decorator = strings.ToLower
var toUpper Decorator = strings.ToUpper
var dec3 Decorator = addConstPrefix
var dec4 Decorator = addConstSuffix
并应用它们:

allDecorators := []Decorator{toUpper, toLower, dec3, dec4}
output := Decorate(input, allDecorators...)
编辑:

参数化装饰器只是返回另一个函数的函数,例如:

func addPrefix(prefix string) func(string) string {
    return func(s string) string {
        return prefix + s
    }
}
然后,可以以下列方式应用:

input2 := "Let's decorate me!"
prefixed := Decorate(input2, []Decorator{addPrefix("Well, ")}...)

首先,decorator基本上是一个函数,它接受另一个特定类型的函数作为参数,并返回一个相同类型的函数。这本质上允许您创建一系列函数。所以在Go中,它看起来像这样:

// this is the type of functions you want to decorate
type StringManipulator func(string) string

// this is your decorator.
func ToLower(m StringManipulator) StringManipulator {
    return func(s string) string {
        lower := strings.ToLower(s)
        return m(lower)
    }
}

对我来说,最困难的是将这一原则应用到其他地方。不幸的是,查看您引用的代码并不能让我更好地理解它,以及如何将其应用于我自己的问题。这对我来说还是太复杂了,我已经创建了一个简单的例子,请看:谢谢你的帮助。真恶心!很高兴它有帮助:)达沃斯,tbh,我现在不完全确定这是否是装饰模式的好例子:)如果我想刷新我的页面,我总是看公认的答案knowledge@srxf上周发布的Go1.9中刚刚添加了类型别名。Upvoting!然而,我正在寻找
return func(s string)string
等形式的Decorator functions模式。此外,对于“”的示例,感谢对参数化Decorator的更新。现在再看一遍代码,我认为您的示例更适合作为更容易理解的示例。如果你先把它放进去,我会选择你的答案。现在我希望我能选择两者。再次感谢您的宝贵帮助!您好@syntagma,仅供参考,我将您的演示代码放在一起,我正在寻找您的
装饰程序
函数应用顺序没有颠倒的原因,当时我意识到,严格来说,您编写的代码不是其他人都在谈论的装饰程序函数模式。为了您的方便,最好的一篇文章解释了Go的Decorator函数模式。这正是我一直在寻找的Go中的Decorator函数模式,非常感谢!如果我理解正确,
AppendDecorator
定义为只能作为第一个操作用于追加?不,
AppendDecorator
与其他函数稍有不同,因为您需要调用它来返回实际的decorator,而实际的decorator是通过要修饰的函数调用的。基本上,它只是为传递给
AppendDecorator
的字符串创建一个闭包,并返回一个新的decorator,然后该decorator可以访问该字符串…@RayfenWindspear可能像
AppendDecoratorFactory
这样的名称更合适。啊哈,现在有意义了。我没有仔细观察返回类型。谢谢啊,不要用工厂这个词来形容Go!!邪恶的爪哇巫毒!这里可以找到一个装饰器模式和23种其他GoF设计模式的简单Go示例。