在Go中使用函数类型

时间:2012-02-22 16:22:51

标签: function types go

我想创建某种类型的函数。我找到了一种方法,但必须有其他更清洁,更好的方法,不包括使用var。声明english类型的函数Greeting有哪些替代方法?

package main

import "fmt"

type Greeting func(name string) string

func (g Greeting) exclamation(name string) string {
    return g(name) + "!"
}

var english = Greeting(func(name string) string {
    return "Hello, " + name
})

func main() {
    fmt.Println(english("ANisus"))
    fmt.Println(english.exclamation("ANisus"))  
}

在上面的例子中,我无法与var english = Greeting...交换english := Greeting...,我也无法删除Greeting(func ...),只是让func独立,从此我赢了无法访问感叹号方法。

2 个答案:

答案 0 :(得分:19)

如果提及var是您的主要问题,可以通过将=更改为:=轻松放弃,如下所示:

english := Greeting(func(name string) string {
    return ("Hello, " + name);
})

但你甚至不必将你的功能转换为Greeting。该规范说明了function types

  

函数类型表示具有相同参数和结果类型的所有函数的集合。

关于type identity

  

如果两个函数类型具有相同数量的参数和结果值,相应的参数和结果类型相同,并且两个函数都是可变参数或两者都不是,则它们是相同的。参数和结果名称不需要匹配。

这意味着每个函数都有自己的函数类型。如果两个函数具有相同的签名(参数和结果类型),则它们共享一个函数类型。通过编写type Greeting func...,您只是为特定的函数类型命名,而不是定义新的函数类型。

所以下面的代码是有效的,我希望在Go中使用正确的方法来处理函数类型:

package main

import "fmt"

type Greeting func(name string) string

func say(g Greeting, n string) { fmt.Println(g(n)) }

func french(name string) string { return "Bonjour, " + name }

func main() {
        english := func(name string) string { return "Hello, " + name }

        say(english, "ANisus")
        say(french, "ANisus")
}

请注意,我还从english函数中删除了分号和括号。如果没有必要,开发人员不会使用这些标点符号。

更新:既然您已提供示例代码,我就可以清楚地了解问题。

为此目的,您的代码足够好,而且没有太多其他方法可以做到这一点。如果你愿意,你可以在调用方法之前进行投射:

english := func(name string) string { return "Hello, " + name }
Greeting(english).exclamation("ANisus")

但我不确定这是一个改进。我只是说,对于你想要做的事情,似乎没有其他方法来编写代码。

也就是说,如果我们不想改变你的类型。我的意思是,在函数类型上调用方法的整个想法似乎有点奇怪。这不是错,但有点罕见。以更常见的方式实现相同效果的另一种方式是通过结构类型并具有该函数的字段。像这样:

package main

import "fmt"

type Greeting struct {
    say func(name string) string
}

func newGreeting(f func(string) string) *Greeting {
    return &Greeting{say: f}
}

func (g *Greeting) exclamation(name string) string { return g.say(name) + "!" }

func main() {
    english := &Greeting{say: func(name string) string {
        return "Hello, " + name
    }}

    french := newGreeting(func(name string) string {
        return "Bonjour, " + name
    })

    fmt.Println(english.exclamation("ANisus"))
    fmt.Println(french.exclamation("ANisus"))
}

此处englishfrench显示了两种不同的编码方式。同样,我并不是说这是更好的解决方案,而是一种更常见,更灵活的方式来实现同样的效果。

答案 1 :(得分:6)

尝试在此处分开问题,

type Greeting func(string) string

func english(name string) string {
    return return "Hello, " + name
}

func main() {
    var g Greeting
    g = english
    fmt.Println(g("ANisus"))
}

是声明类型为Greeting的函数english的方法。注意问候语未在英语定义中使用,因此这可能无法满足您声明特定类型函数的要求。否则,抱歉,Go中没有办法定义特定(即单独定义)类型的函数。输入类似

的内容可能会更好
english := Greeting {
    return return "Hello, " + name
}

但不,Go中没有办法。英语声明不能使用Greeting,必须重复功能签名。相反,英语属于Greeting类型的要求仅在作业中进行

g = english

g声明为Greeting类型。如果英语不是同一类型,则该行不会编译。

除了重复类型签名的问题 - 例如方法的问题 - 目前还不清楚你是否还在寻找其他方法来组织你的例子的功能。它当然可以通过其他方式完成。然而,一个更大的例子可能会有所帮助。