这段 go 代码始终理解不到

2024-03-13 17:27:51 +08:00
 Grocker
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,始终理解不到

7543 次点击
所在节点    Go 编程语言
69 条回复
0Z03ry75kWg9m0XS
2024-03-13 20:18:04 +08:00
防御性编程 + 1
Grocker
2024-03-13 20:29:04 +08:00
@xgfan 对 go 了解不深
Jooeeee
2024-03-13 21:23:35 +08:00
@root71370 因吹斯汀,高数跟编程语言建立了连接
wweerrgtc
2024-03-13 23:02:13 +08:00
结合另一个例子 应该可以看懂
mellowmemories
2024-03-13 23:25:48 +08:00
没学过 GO ,浅浅懵一下。

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

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

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

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

看这个帖才知道,Go 连 func 都能当类型,有点野哈哈。
gowk
2024-03-14 09:25:11 +08:00
想知道 Rust 里面是不是也有类似的写法?
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
2024-03-14 09:47:57 +08:00
@journalistFromHK 卧槽 还想着带个格式来着
CHchenkeyi
2024-03-14 10:28:27 +08:00
他们都说的复杂了,其实很好理解,因为 english 的函数签名和 Greeting 一致,所以可以转换,这边是转换就像 int64 ->int , 是不是就是 int(int64) 这种写法, 那么 greet 就是 english ,然后调用了 say ('world')=>greet(n) 方法, 实际上就是 english('world)
F7TsdQL45E0jmoiG
2024-03-14 11:12:11 +08:00
函数式编程还是 LISP 那种看着舒服
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
2024-03-14 11:38:27 +08:00
把方法强转为了函数对象。写惯 pojo 容易以为是构造函数了
cmsyh29
2024-03-14 11:40:21 +08:00
go 只是语法简单,上手程度我觉得不如 java
zhoujx
2024-03-14 11:42:53 +08:00
就是有点绕而已
gkinxin
2024-03-14 14:05:48 +08:00
@Livid #1 2677672 #11 zrlhk gpt 回答
iceiceice9527
2024-03-14 14:16:14 +08:00
重点:函数可以是变量。。
JoeJasper
2024-03-14 15:00:27 +08:00
go 语言里的 duck typing (鸭子类型)
Megrax
2024-03-14 15:01:55 +08:00
@xuing 谢谢,看到“强转”这两个字就懂了
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 里面我没看到明确说法。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1023324

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX