这段 go 代码始终理解不到 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
Grocker
V2EX    Go 编程语言

这段 go 代码始终理解不到

  •  
  •   Grocker 2024-03-13 17:27:51 +08:00 7689 次点击
    这是一个创建于 624 天前的主题,其中的信息可能已经有所发展或是发生改变。
    package main import "fmt" type Greeting func(name string) string func (g Greeting) say(n string) { fmt.Println(g(n)) } func english(name string) string { return "Hello, " + name } func main() { greet := Greeting(english) greet.say("World") } 

    这段代码为什么会输出 Hello, World,始终理解不到

    69 条回复    2024-04-04 22:14:23 +08:00
    LsLsLsLsLs
        1
    LsLsLsLsLs  
       2024-03-13 17:32:12 +08:00   1
    定义 Greeting 类型:

    go
    Copy code
    type Greeting func(name string) string
    这里定义了一个新的类型 Greeting ,它是一个函数签名。这意味着任何具有相同签名(即接受一个 string 类型的参数并返回一个 string 类型)的函数都可以被看作是一个 Greeting 类型。

    为 Greeting 类型添加 say 方法:

    go
    Copy code
    func (g Greeting) say(n string) {
    fmt.Println(g(n))
    }
    这个方法接受一个 Greeting 类型的接收器和一个 string 类型的参数。在这个方法内部,它调用了 Greeting 类型的函数(这里的 g ),传入了 n 作为参数,并打印了该函数的返回值。因为 Greeting 是一个函数类型,所以这里 g(n) 实际上是在调用这个函数。

    定义 english 函数:

    go
    Copy code
    func english(name string) string {
    return "Hello, " + name
    }
    这是一个简单的函数,接受一个 string 类型的参数,并返回一个新的 string ,其中包含了问候语。这个函数符合 Greeting 类型的定义。

    在 main 函数中使用:

    go
    Copy code
    func main() {
    greet := Greeting(english)
    greet.say("World")
    }
    这里首先将 english 函数转换成 Greeting 类型,并赋值给 greet 变量。这是可能的,因为 english 符合 Greeting 类型的定义。
    然后,调用了 greet 的 say 方法,并传入了 "World" 作为参数。这将会打印 "Hello, World",因为 english 函数被调用,并以 "World" 作为参数。
    这个程序的核心思想是通过函数类型和方法,实现了对函数的封装和扩展。在这个例子中,Greeting 函数类型通过添加 say 方法,能够以一种更结构化的方式使用函数。这种模式在 Go 中是一种强大的设计方式,允许开发者以灵活且富有表达力的方式编写代码。
    Grocker
        2
    Grocker  
    OP
       2024-03-13 17:36:04 +08:00
    @2677672 chatgpt?
    deplives
        3
    deplives  
       2024-03-13 17:38:04 +08:00
    很难理解么?
    say 里面是啥?不就一个 g(n) 么
    g 是啥,g 不就是 func english
    n 是啥 n 不就是 "World"

    那 g(n) 不就是 english("World")
    fmt.Println(g(n)) 不就应该是 Hello, World
    seers
        4
    seers  
       2024-03-13 17:39:00 +08:00 via Android   5
    pass func like pass value
    hemingway
        5
    hemingway  
       2024-03-13 17:41:13 +08:00   2
    type Greeting func(name string) string 因为这个 typedef ,所以
    greet := Greeting(english)
    这一行的效果是,greet := english
    那么 say 里面:
    fmt.Println(g(n)) 等价于 fmt.Println(english(n))
    Kumo31
        6
    Kumo31  
       2024-03-13 17:41:21 +08:00   1
    做等价代换就清晰了,首先可以看成
    func say(g Greeting, name string) {
    fmt.Println(g(name))
    }

    func main() {
    say(Greeting(english), "World")
    }

    然后
    func say(g func(name string) string, name string) {
    fmt.Println(g(name))
    }

    func main() {
    say(english, "World")
    }

    接着
    func say(name string) {
    fmt.Println(english(name))
    }

    func main() {
    say("World")
    }

    最后

    func say(name string) {
    fmt.Println("Hello, " + name)
    }

    func main() {
    say("World")
    }
    xuing
        7
    xuing  
       2024-03-13 17:43:23 +08:00   2
    Greeting 是接口,english 是实现,通过 Greeting(english)进行了强转。调用 say 方法,say 方法里面的 g(n)就是调用 english 方法本身。

    GPT4 say:

    这段代码定义了一个函数类型 `Greeting`,一个接受字符串并返回字符串的函数。`english` 函数符合 `Greeting` 类型的定义,因此可以将 `english` 函数转换为 `Greeting` 类型,并赋值给变量 `greet`。

    `Greeting` 类型还定义了一个方法 `say`,该方法接受一个字符串参数 `n`,并使用 `Greeting` 类型的函数(本例中是 `english` 函数)处理这个参数,然后输出结果。

    这里是具体的步骤:

    1. 定义 `Greeting` 类型为一个函数类型,它接受一个 `string` 类型的参数,并返回一个 `string` 类型的结果。
    2. 定义 `english` 函数,该函数符合 `Greeting` 类型:接受一个 `string` 类型的参数,返回一个拼接了 "Hello, " 和参数的 `string` 类型的结果。
    3. 在 `main` 函数中,将 `english` 函数转换为 `Greeting` 类型,并赋值给 `greet` 变量。
    4. 调用 `greet` 变量的 `say` 方法,并传递 "World" 作为参数。
    5. `say` 方法内部调用 `greet`(即 `english` 函数),传递 "World" 作为参数,

    得到返回值 "Hello, World"。
    6. 使用 `fmt.Println` 输出这个返回值。

    所以,当运行这段代码时,它会输出 "Hello, World"。这是因为 `greet.say("World")` 实际上是调用 `english` 函数,将 "World" 作为参数,然后输出结果。
    LsLsLsLsLs
        8
    LsLsLsLsLs  
       2024-03-13 17:45:52 +08:00
    @Grocker
    prenwang
        9
    prenwang  
       2024-03-13 17:47:36 +08:00
    在 Go 中,函数是一等公民, 函数式编程, 非常巧妙。

    Greeting(english) 是函数转换, 函数签名必须一致, 也就是参数,返回值都必须一致。

    适用的场景太多了, 比如回调函数,web 框架的中间件等

    同时也体现了 go 的类型模式的优点, 把静态语言玩出这种魔法确实强。
    tangqiu0205
        10
    tangqiu0205  
       2024-03-13 17:50:05 +08:00   1
    首先定义了 Greeting 为 func 类型, 并且他有一个 say 方法.
    greet := Greeting(english) 这段是把 english 转换成 Greeting 类型,
    所以 greet 可以调用 say()方法, 又由于 say 方法有接收者类型 g,
    g 是一个 func 类型,所以这块可以调用 g 的方法.
    zrlhk
        11
    zrlhk  
       2024-03-13 17:50:28 +08:00
    这段 Go 语言程序定义了一个简单的示例,用于展示函数类型和方法的使用。让我逐步解释这段代码:

    首先,通过 package main 声明该程序是一个可独立运行的程序,并且在编译后会生成可执行文件。

    import "fmt"引入了 Go 语言标准库中的 fmt 包,用于格式化输入输出。

    接着定义了一个类型为 func(name string) string 的别名 Greeting ,表示这是一个接收 string 类型参数并返回 string 类型结果的函数类型。

    然后定义了一个方法 say ,该方法属于类型 Greeting ,接收一个 string 类型参数 n ,通过调用 g(n)来输出对应的问候语。

    接下来定义了一个普通函数 english ,实现了一个简单的英文问候功能,接收一个 name 参数,返回"Hello, " + name 的字符串。

    在 main 函数中,创建了一个变量 greet ,将类型为 Greeting 的 english 函数赋值给它,相当于将 english 函数转换为 Greeting 类型的变量 greet 。

    最后通过 greet.say("World")调用了 say 方法,传入参数"World",实际上是调用了 english 函数并输出了"Hello, World"这个问候语。

    总结:这段代码演示了如何定义函数类型、方法以及函数的转换与调用。通过这个示例,展示了 Go 语言中函数类型和方法的灵活性和方便性。
    MIUIOS
        12
    MIUIOS  
       2024-03-13 17:53:36 +08:00
    相当于定义了一个接口, 下面就是实现的方法,这么理解好理解点。
    dhb233
        13
    dhb233  
       2024-03-13 17:58:08 +08:00
    我已经尽力去写个好理解的变量名字了,有点长

    package main

    import "fmt"

    type strFunc func(name string) string

    func (g strFunc) callFuncAndPrintReturnVal(n string) {
    fmt.Println(g(n))
    }

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

    func main() {
    addHelloPrefixFunc := strFunc(addHelloPrefix)
    addHelloPrefixFunc.callFuncAndPrintReturnVal("World")
    }
    PlG5sBkXD1ziLeGB
        14
    PlG5sBkXD1ziLeGB  
       2024-03-13 18:03:05 +08:00 via iPhone
    很典型的 callback 用法,适用于 func 作为参数的场景
    tinyfry
        15
    tinyfry  
       2024-03-13 18:09:29 +08:00
    Greeting 和 english 的签名相同
    deorth
        16
    deorth  
       2024-03-13 18:53:51 +08:00 via Android
    你以前是写啥的,没有变量存函数的概念么
    6IbA2bj5ip3tK49j
        17
    6IbA2bj5ip3tK49j  
       2024-03-13 19:20:19 +08:00 via iPhone
    好奇,是初学者吗……
    root71370
        18
    root71370  
       2024-03-13 19:30:26 +08:00
    像高数的换元法。。
    lcy
        19
    lcy  
       2024-03-13 19:31:07 +08:00
    类似 C 的类型转换 greet = (Greeting) english
    NessajCN
        20
    NessajCN  
       2024-03-13 19:56:53 +08:00
    这个你如果会一点 js 就特别清晰了,就是把函数当成个变量
    譬如这里的 english ,虽然它是个函数,但你可以把他当成跟 i := 1 这样的 i 一样的东西
    你可以理解称 english := func(n string) string { return "Hello, " + n }
    那既然是个变量,你就可以把它放进类型里 , 就像这里的 Greeting
    然后下面定义的 Greeting 的方法 say, 根据它的实现,g 其实就是 english, 那 g(n) 就是 english(n)
    那么 greet.say("World") 就等于 fmt.Println(english("World"))
    0Z03ry75kWg9m0XS
        21
    0Z03ry75kWg9m0XS  
       2024-03-13 20:18:04 +08:00   1
    防御性编程 + 1
    Grocker
        22
    Grocker  
    OP
       2024-03-13 20:29:04 +08:00
    @xgfan 对 go 了解不深
    Jooeeee
        23
    Jooeeee  
       2024-03-13 21:23:35 +08:00
    @root71370 因吹斯汀,高数跟编程语言建立了连接
    wweerrgtc
        24
    wweerrgtc  
       2024-03-13 23:02:13 +08:00   2
    结合另一个例子 应该可以看懂
    mellowmemories
        25
    mellowmemories  
       2024-03-13 23:25:48 +08:00
    没学过 GO ,浅浅懵一下。

    首先创建了一个 lambda 表达式 Greeting ,定义了一种行为,该行为接收一个 string,并返回一个 string 。

    在 main 函数的第一行,将复合上文中的定义的 english 函数包装成指定的 Greeting lambda 。

    然后 say 函数,似乎是被定义在 Greeting 名下的,作为其方法。
    uiosun
        26
    uiosun  
       2024-03-14 00:25:34 +08:00
    给到一个回调函数作为类型,进行后续的类型下的方法处理

    JS 、PHP 蛮多这种的,没啥特别。

    看这个帖才知道,Go 连 func 都能当类型,有点野哈哈。
    gowk
        27
    gowk  
       2024-03-14 09:25:11 +08:00
    想知道 Rust 里面是不是也有类似的写法?
    journalistFromHK
        28
    journalistFromHK  
       2024-03-14 09:46:44 +08:00
    <p>正在学 go,还没见过 type 为 func 的,以前都是 struct...</p>
    <p>按照我这种新手的理解(应该和楼主一样吧),</p>
    <p>核心就是理解 fmt.Println(g(n)),</p>
    <p>其实在 greet := Greeting(english)之后 greet 就等于 english 了,</p>
    <p>所以 g(n)就等于 english(n),n 又是由 say 的"world"传入...</p>
    <p>最后就相当于执行了 english,参数是 say("world")的参数</p>
    journalistFromHK
        29
    journalistFromHK  
       2024-03-14 09:47:57 +08:00
    @journalistFromHK 卧槽 还想着带个格式来着
    CHchenkeyi
        30
    CHchenkeyi  
       2024-03-14 10:28:27 +08:00
    他们都说的复杂了,其实很好理解,因为 english 的函数签名和 Greeting 一致,所以可以转换,这边是转换就像 int64 ->int , 是不是就是 int(int64) 这种写法, 那么 greet 就是 english ,然后调用了 say ('world')=>greet(n) 方法, 实际上就是 english('world)
    F7TsdQL45E0jmoiG
        31
    F7TsdQL45E0jmoiG  
       2024-03-14 11:12:11 +08:00
    函数式编程还是 LISP 那种看着舒服
    strconv
        32
    strconv  
       2024-03-14 11:23:36 +08:00
    > Go 语言中的方法( Method )是一种作用于特定类型变量的函数。这种特定类型变量叫做接收者( Receiver )
    - say 称作方法,(g Greeting)称之为接收者。
    - 方法也是一种函数,接收者也是一个参数

    ```go
    type Greeting func(string) string

    // say 方法接收者
    func (g Greeting) say(name string) {
    fmt.Println(g(name))
    }

    // say2
    // 方法接收者等效于把一个参数前置了,翻译过来就是下面这个函数
    // 这个函数就好理解了
    // 入参:处理字符串的函数、字符串
    // 功能:调用 函数 去处理 字符串
    func say2(g Greeting, name string) {
    fmt.Println(g(name))
    }

    ```
    cmsyh29
        33
    cmsyh29  
       2024-03-14 11:38:27 +08:00
    把方法强转为了函数对象。写惯 pojo 容易以为是构造函数了
    cmsyh29
        34
    cmsyh29  
       2024-03-14 11:40:21 +08:00   1
    go 只是语法简单,上手程度我觉得不如 java
    zhoujx
        35
    zhoujx  
       2024-03-14 11:42:53 +08:00
    就是有点绕而已
    gkinxin
        36
    gkinxin  
       2024-03-14 14:05:48 +08:00
    @Livid #1 2677672 #11 zrlhk gpt 回答
    iceiceice9527
        37
    iceiceice9527  
       2024-03-14 14:16:14 +08:00
    重点:函数可以是变量。。
    JoeJasper
        38
    JoeJasper  
       2024-03-14 15:00:27 +08:00
    go 语言里的 duck typing (鸭子类型)
    Megrax
        39
    Megrax  
       2024-03-14 15:01:55 +08:00
    @xuing 谢谢,看到“强转”这两个字就懂了
    FYFX
        40
    FYFX  
       2024-03-14 16:00:07 +08:00
    我不懂 go,不过 我好奇回复里面说强转的,这个转换真的发生了吗(由编译器做的)?

    > A function type denotes the set of all functions with the same parameter and result types. The value of an uninitialized variable of function type is nil. https://go.dev/ref/spec#Function_types

    我查了一下 golang 的函数类型是不不包括函数名的,所以 Greeting 和 english 就是同一个函数类型。至于 golang 函数签名和函数类型是不是一回事,也就是说是否包含函数名称这点我看两种说法都有,spec 里面我没看到明确说法。
    leonshaw
        41
    leonshaw  
       2024-03-14 16:23:03 +08:00   1
    @FYFX
    Greeting 是一个新的类型,它的 underlying 类型是 func(name string) string
    english 是一个签名是 func(name string) string 的函数
    aw2350
        42
    aw2350  
       2024-03-14 16:26:41 +08:00
    多态,委托 ,先好好补习一下面向对象
    yiqiao
        43
    yiqiao  
       2024-03-14 16:32:40 +08:00
    OP 有用过 PHP 吗?类似:call_user_func_array
    flyv2x
        44
    flyv2x  
       2024-03-14 16:36:56 +08:00
    简单说,其实你的例子,如果去掉 type 定义,直接等价于下面代码:
    ```
    package main

    import "fmt"

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

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

    func main() {
    say(english, "World")
    }
    ```
    CHchenkeyi
        45
    CHchenkeyi  
       2024-03-14 16:39:29 +08:00
    他们都说的复杂了,其实很好理解,因为 english 的函数签名和 Greeting 一致,所以可以转换,这边是转换就像 int64 ->int , 是不是就是 int(int64) 这种写法, 那么 greet 就是 english ,然后调用了 say ('world')=>greet(n) 方法, 实际上就是 english('world)
    Rache1
        46
    Rache1  
       2024-03-14 16:55:22 +08:00
    就是存了个回调函数吧,等效于 JS 的。


    function Foo (func) {
    this._func = func;

    this.say = function (str) {
    console.log(this._func(str));
    };

    if (!(this instanceof Foo)) {
    return new Foo(func);
    }
    }

    function english (str) {
    return 'Hello, ' + str;
    }

    // 1
    Foo(english).say('World');

    // 2
    (new Foo(english)).say('World');
    zhangyq008
        47
    zhangyq008  
       2024-03-14 17:01:49 +08:00
    类似接口型函数,用处多多
    看下这篇文章 https://geektutu.com/post/7days-golang-q1.html
    hb751968840
        48
    hb751968840  
       2024-03-14 17:14:51 +08:00
    js 好理解
    function english(name) {
    return "Hello, " + name
    }
    function Greeting (english) {
    return {
    say: (name) => {
    english(name)
    }
    }
    }
    function main() {
    const greet = Greeting(english)
    greet.say("World")
    }
    largezhou
        49
    largezhou  
       2024-03-14 17:19:25 +08:00
    首先 Greeting 的类型是一个函数
    然后 english 这个函数跟 Greeting 的函数签名一样
    所以可以把 english 这个函数,强转成 Greeting 类型,即:greet := Greeting(english)
    然后调用 Greeting 的“实例”方法 say
    由于 Greeting 本身是个函数,可以直接调用,say 里面就是调用 g(n)
    实际就是调用的 english("World")
    Vegetable
        50
    Vegetable  
       2024-03-14 17:25:25 +08:00
    写成这样同事不打人的吗
    svnware
        51
    svnware  
       2024-03-14 17:49:20 +08:00
    学过 C/C++的,一看就明白
    sztink
        52
    sztink  
       2024-03-14 17:50:45 +08:00
    **方法本质就是普通的函数,方法的接收者就是隐含的第一个参数。**

    ```go
    greet.say("World");
    say(greet, "World");
    ```
    上面两者是等效的,从这个角度理解就简单了不少。具体介绍可以看:[深入 Go 语言之旅: 方法]( https://go.cyub.vip/function/method/)
    via
        53
    via  
       2024-03-14 18:08:52 +08:00   1
    鸭子类型,english 入餐像鸭子,出餐也像鸭子,那我们就可以认为 English 就是鸭子。

    上面的鸭子就是 Greeting
    via
        54
    via  
       2024-03-14 18:09:44 +08:00
    OP 可以断言下:english.(Greeting) 看看会不会报错
    sztink
        55
    sztink  
       2024-03-14 18:44:13 +08:00
    @sztink 回复咋不支持 markdown 格式,另外怎么发链接,我发的链接都显示成纯文本(没使用 markdown ,直接发个链接也这样),看别人发的可以直接点击?有 V 友可以告知怎么操作链接吗。
    FengMubai
        56
    FengMubai  
       2024-03-14 19:19:13 +08:00
    你在`return "Hello, " + name`处打个断点, 观察调用栈能就明白
    cosiner
        57
    cosiner  
       2024-03-14 20:05:49 +08:00
    type 类型名称 类型定义

    type Greeting func(name string)
    type Name string
    type Data struct {
    Name string
    }

    type 类型名称 类型名称
    type Data2 Data


    Go 里面自己使用 type 定义的新类型名称都可以给它加方法,
    你这个例子里面是把 english 相当于是匿名的 func(string)类型, 然后把它转换成了 Greeting 类型(实际都是 func(string)类型,Go 里面能随便转换), 就可以调用 Greeting 的 say 方法了,和接口,鸭子类型没关系
    wqtacc
        58
    wqtacc  
       2024-03-14 20:24:18 +08:00
    ```go
    package main

    import "fmt"

    // Greeting 定义为一个函数
    type Greeting func(name string) string

    func (g Greeting) say(n string) {
    // g 调用函数自身
    s := g(n)
    fmt.Println(s)
    }

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

    func main() {
    // english 函数与 Greeting 签名相同,进行强转
    greet := Greeting(english)
    greet.say("World")


    var greet2 Greeting = func(s string) string {
    return "Hello, " + s
    }
    fmt.Println(greet2("World!"))
    greet2.say("World!")
    }

    ```
    wqtacc
        59
    wqtacc  
       2024-03-14 20:26:08 +08:00
    ```go
    package main

    import "fmt"

    // Greeting 定义为一个函数
    type Greeting func(name string) string

    func (g Greeting) say(n string) {
    // g 调用函数自身
    s := g(n)
    fmt.Println(s)
    }

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

    func main() {
    // english 函数与 Greeting 签名相同,进行强转
    greet := Greeting(english)
    greet.say("World")

    // 完整的长生命方法, 同时去除 english 的干扰项
    var greet2 Greeting = func(s string) string {
    return "Hello, " + s
    }
    fmt.Println(greet2("World!"))
    greet2.say("World!")
    }

    ```
    yuzo555
        60
    yuzo555  
       2024-03-14 21:59:39 +08:00
    Claude 3 的解释:
    这段代码的输出 "Hello, World" 是因为以下几个原因:

    1. 在代码中定义了一个名为 Greeting 的函数类型,它是一个接受字符串参数,并返回字符串的函数。

    2. 定义了一个名为 english 的函数,它满足 Greeting 类型的要求,即接受一个字符串参数,并返回一个字符串 "Hello, " 加上传入的参数。

    3. 在 main 函数中,创建了一个名为 greet 的变量,它的类型是 Greeting,并将 english 函数转换为 Greeting 类型赋值给了 greet 。

    4. 对于 Greeting 类型的变量,Go 语言会自动为其提供一个 say 方法,这个方法接受一个字符串参数,并调用 Greeting 类型的函数,传入该字符串参数。

    5. 在 main 函数中,调用了 greet.say("World")。这相当于先调用了 greet("World"),也就是调用了 english("World")函数,该函数返回了 "Hello, World"。然后将这个返回值作为参数打印出来。

    所以,最终输出的就是 "Hello, World"。这段代码展示了 Go 语言中将函数作为值进行传递和赋值的能力,以及通过为某个类型定义方法来扩展其功能的特性。

    在这段代码中,比较难以理解的一个点是:

    func (g Greeting) say(n string) {
    fmt.Println(g(n))
    }
    这里为 Greeting 类型(它是一个函数类型)定义了一个 say 方法。

    具体来说,有以下几点需要注意:

    1. Greeting 是一个函数类型,它本身并不是一个具体的函数值,而是一种函数签名的描述。

    2. Go 语言允许为任何命名类型(包括内置类型和自定义类型)定义方法,这里是为 Greeting 这个函数类型定义了一个 say 方法。

    3. say 方法的接收者是 g Greeting,表示这个方法会为所有 Greeting 类型的值(函数值)提供 say 方法。

    4. 在 say 方法的实现中,它直接以调用函数的方式 g(n) 来执行该 Greeting 类型的函数值,并将结果打印出来。

    这种为函数类型定义方法的做法,看起来有点违反直觉,因为我们一般会认为方法只能为结构体或对象这样的数据类型定义。但在 Go 语言中,函数作为一等公民,也可以为其定义方法。

    这样做的好处是,可以为某个函数类型扩展一些通用的辅助方法,而不需要为每个具体的函数值都实现这些方法。这提高了代码的可重用性和可维护性。
    2kCS5c0b0ITXE5k2
        61
    2kCS5c0b0ITXE5k2  
       2024-03-14 23:31:04 +08:00
    类型别名
    Subfire
        62
    Subfire  
       2024-03-15 10:06:19 +08:00

    greet := Greeting(english)
    greet.say("World")
    换成
    var greet2 Greeting = english
    greet2.say("World")
    是不是更容易理解点了?
    Jessec
        63
    Jessec  
       2024-03-15 10:27:41 +08:00
    我一开始也蒙,仔细观察发现这一行代码实际上是把 english 的类型转换成了 Greeting
    greet := Greeting(english)
    lilei2023
        64
    lilei2023  
       2024-03-15 14:25:23 +08:00
    貌似就是转换了一下类型,然后把函数作为参数传进去了,前端不经常这么干么??
    lilei2023
        65
    lilei2023  
       2024-03-15 14:28:18 +08:00
    @lilei2023 更正一下,没传!看错了!
    sunzhenyucn
        66
    sunzhenyucn  
       2024-03-15 14:36:01 +08:00
    这样写不是闲的吗?同事应该会打人吧(逃
    sztink
        67
    sztink  
       2024-03-18 11:42:31 +08:00
    @sunzhenyucn 很常见的一个技巧,经常用来将一个普通函数包裹成实现特定接口。比如上面就是 english 这个普通函数可以变成实现 say 方法的接口对象。Go 源码 net/http 里面有使用到 https://github.com/golang/go/blob/master/src/net/http/server.go#L2158-L2167 。包 robfig/cron 里面的 https://github.com/robfig/cron/blob/master/cron.go#L133-L154
    sunzhenyucn
        68
    sunzhenyucn  
       2024-03-21 16:59:02 +08:00
    @sztink 学到了 谢谢
    kenilalexandra
        69
    kenilalexandra  
       2024-04-04 22:14:23 +08:00
    感觉并没有多难理解,Greeting 类型接收函数作为参数,say 函数由于是继承了 Greeting 的所有 greet 实际可以直接调用 say 函数不就完事了?难道说是你没理解函数也可以当作变量进行传递还是?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1330 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 23:57 PVG 07:57 LAX 15:57 JFK 18:57
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86