在Go中使用函数类型

ANi*_*sus 12 types function 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"))  
}
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,我不能交换var english = Greeting...使用english := Greeting...,我也不能删除Greeting(func ...),只是有func独立从那时起,我将无法访问感叹方法.

Mos*_*afa 23

如果一提的var是你的主要问题,你可以轻松地删除它,通过改变=:=,就像这样:

english := Greeting(func(name string) string {
    return ("Hello, " + name);
})
Run Code Online (Sandbox Code Playgroud)

但你甚至不必将你的功能投入Greeting.规范说明了函数类型:

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

这与类型标识有关:

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

这意味着每个函数都有自己的函数类型.如果两个函数具有相同的签名(参数和结果类型),则它们共享一个函数类型.通过编写,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")
}
Run Code Online (Sandbox Code Playgroud)

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

更新:现在您已经提供了示例代码,我可以清楚地了解问题.

为此,您的代码足够好,并没有太多其他方法可以做到这一点.如果您愿意,可以在调用方法之前进行转换:

english := func(name string) string { return "Hello, " + name }
Greeting(english).exclamation("ANisus")
Run Code Online (Sandbox Code Playgroud)

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

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

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"))
}
Run Code Online (Sandbox Code Playgroud)

这里englishfrench显示编码同一件事的两种不同的方式.同样,我并不是说这是更好的解决方案,而是一种更通常,更灵活的方式来实现同样的效果.

  • 感谢您的回答。但是我的问题是如何声明特定类型的函数。在您的代码示例中,您永远不会那样做。我已经更新了我的示例,并且您可能会注意到,当您向类型添加方法时,除非执行`Greeting(func(name string)...)部分,否则您将无法访问它。 (2认同)

Son*_*nia 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"))
}
Run Code Online (Sandbox Code Playgroud)

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

english := Greeting {
    return return "Hello, " + name
}
Run Code Online (Sandbox Code Playgroud)

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

g = english
Run Code Online (Sandbox Code Playgroud)

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

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

  • 我有点想用`english:= Greeting {...}`行来寻找你所说明的内容,在那里你解释说没有这样的方法.但是你让我进一步了解了如何以Go惯用的方式使用函数类型. (2认同)