Go最重要的特性是:隐形异步


当被问及 Go 最重要的特性时,许多人会谈论 Go 的简单性、C 互操作性、编译速度等。
然而,Go 的最佳特性是在同步接口中编写异步代码的能力。
作者给出了一个在 Go 与 Java 中发出的 HTTP 请求的示例,以展示 Go 如何非常有效地调度工作。
 
Go代码:

package main

import (
  "fmt"
 
"log"
 
"net/http"
)

func main() {
  http.HandleFunc(
"/", func(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintln(w,
"Goodbye, World!")
  })
  log.Fatal(http.ListenAndServe(
":8080", nil))
}

上述Go 标准运行时允许异步编码,同时允许开发人员使用简单的同步接口。但由于它是标准 Go 运行时的一部分,因此它是不可见的invisible 。
为了更好地突出该特性,让我们看一个用 Java 编写的类似代码的示例。

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

public class HelloWorld {

    public static void main(String[] args) throws Exception {
        HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
        server.createContext("/", new MyHandler());
        server.setExecutor(null);
// creates a default executor
        server.start();
    }

    static class MyHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange t) throws IOException {
            String response =
"Goodbye, World!";
            t.sendResponseHeaders(200, response.length());
            OutputStream os = t.getResponseBody();
            os.write(response.getBytes());
            os.close();
        }
    }

}

为了使这个代码和 Go 代码一样好,你需要做很多额外的工作。
我正在谈论的特性是阻塞 goroutine 的 Go 运行时处理。当我第一次开始使用 Go 时,我认为 goroutines 是 Java 的绿色线程上更有效的变体,但是当我编写看起来像传统阻塞 I/O 的代码时,它从未意识到它实际上更类似于异步 I/O . 很明显,在进行阻塞调用时,Go 能够更有效地安排工作。要从 Java 中获得这种性能,您需要添加线程池、future或其他一些异步库。
 
性能测试结果:Java 版本每秒达到约 21K 请求,而 Go 版本每秒达到约 36K 请求。