python - Groovy 中是否有与 Python 的 yield 行为等价的行为?
问题描述
尝试学习 Groovy,到目前为止,这是一次有趣且略微令人困惑的冒险。我目前正在尝试做的是建立一个服务器,wget
向它发出请求,当收到该请求时,执行某个操作 - 在这种情况下,只需创建一个新文件:
import java.net.http.HttpResponse
class ServerLogic {
static def holdupServer() {
println('Standing up server..\n')
def socketServer = new ServerSocket(5000)
// server is up
socketServer.accept { socket ->
// the lines below only execute when a connection is made to the server
socket.withStreams { input, output ->
println("[${new Date()}] HELLO\n")
def newFile = new File("/home/nick/IdeaProjects/groovy_learning/resources/new.txt")
newFile.createNewFile()
newFile.text = 'Hello!!!'
println("NEW FILE SHOULD HAVE BEEN CREATED.")
println ">> READ: ${input.newReader().readLine()}"
}
}
return HttpResponse
}
}
ServerLogic.holdupServer()
使用上面的代码,当我执行 a 时wget http://localhost:5000
,它“工作”,因为文件是按照我想要的方式创建的,但wget
输出不满意:
--2021-07-17 15:42:32-- http://localhost:5000/
Resolving localhost (localhost)... 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:5000... connected.
HTTP request sent, awaiting response... No data received.
Retrying.
--2021-07-17 15:42:33-- (try: 2) http://localhost:5000/
Connecting to localhost (localhost)|127.0.0.1|:5000... failed: Connection refused.
Resolving localhost (localhost)... 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:5000... failed: Connection refused.
// these occur because the server has shut down after the last println call, when the `return HttpResponse` triggers
因此,我们可以推断出没有返回正确的响应,即使我有return HttpResponse
aftersockerServer.accept ...
逻辑。我对如何解决问题的想法(主要是因为我来自 Python 背景)将以某种方式模仿yield
Python 中的响应(基本上,在不中断holdupServer()
逻辑并因此中断服务器连接的情况下返回响应)。有没有办法在 Groovy 中实现这一点,或者有没有一种不同的方法可以用来在HttpResponse
不退出holdupServer()
块的情况下基本上返回有效值?
解决方案
解释
您可以使用函数回调,它在 Groovy 中转换为闭包回调。基本上,您将要返回的值传递给另一个函数/方法,以延迟当前方法上的堆栈。这种方法基本上适用于所有语言。例如,在 java(不支持 lambda 的版本)中,您必须传递一个对象,稍后您将在该对象中调用一个方法。
例子
import java.net.http.HttpResponse
class ServerLogic {
static def holdupServer(Closure closure) {
(0..2).each {
closure.call(HttpResponse)
}
}
}
ServerLogic.holdupServer { httpResponse ->
println httpResponse
}
输出
interface java.net.http.HttpResponse
interface java.net.http.HttpResponse
interface java.net.http.HttpResponse
解决 OP 的评论
您必须提供一些标题。至少Content-Type
并且Content-Length
应该连同格式正确的数据和 HTTP 状态(在本例中为 HTTP/1.1 200)一起提供。此外,您应该将ServerSocket.accept
调用包装在一个 while 循环中。
请参阅有关 HTTP 的 MDN概述。
代码
class ServerLogic {
static HEADERS = [
"HTTP/1.1 200",
"Content-Type: text/html; charset=utf-8",
"Connection: Keep-Alive",
"Keep-Alive: timeout=5, max=1000",
"Content-Length: %d\r\n",
"%s"
].join("\r\n")
static def holdupServer(Closure callback) {
println('Standing up server..\n')
def socketServer = new ServerSocket(5000)
// server is up
while(true) { // Continue to accept connections
socketServer.accept { socket ->
// the lines below only execute when a connection is made to the server
callback.call(socket) // call function
}
}
}
}
ServerLogic.holdupServer { Socket socket ->
String data = "RESPONSE <--\n"
def response = String.format(ServerLogic.HEADERS, data.size(), data)
println response
socket << response
}
客户端输出
RESPONSE <--
推荐阅读
- php - 如何在 jquery 自动完成插件中提供多个源参数?
- python - 在 Windows 上的 Ubuntu 上使用 os.path.join
- vba - Excel VBA将值与列进行比较
- java - 从 TLS 获取证书链以使用 OCSP
- javascript - 无法为 React Native 应用设置 Twitter 身份验证。错误:未确认的回调
- android - 无法获取未知属性“sonatypeRepo”
- java - Bits.java 中的“0x0102030405060708L”是什么
- swift-mt - SWIFT MT 消息 SEME 唯一性
- c# - 根据消费页面中定义的值在布局中呈现 html 内容
- php - 错误:找不到类“PHPMailer”