从一个 PHP 工程师的角度来看 Go

翻译 Summer ⋅ 于 1个月前 ⋅ 最后回复由 an0nym0us 3周前 ⋅ 1388 阅读 ⋅ 原文地址
这是一篇协同翻译的文章,目前翻译进度为 54%,你可以点击『我来翻译』按钮来 参与翻译

file

作为一个 PHP 工程师,你有时是否想过要精通一门其他编程语言?

PHP 曾是一个由许多企业构建大型全栈项目的的首选语言。此外, 在过去的五年中下列框架 (SymfonyLaravel, Zend),工具 (Composer, Monolog) 和迅速成长的社区 (PHP-FIG) 帮助过诸多工程师去构建企业型应用。像 Facebook,Yahoo!,Wikipedia,Wordpress,Tumblr 之类的公司在创业之初都使用过原生 PHP 进行开发,这些随后都促使他们走向成功。

Symphony 翻译于 1个月前

然而,一家成功公司的发展,需要更多的工程师来支持。因此公司庞大的组织架构最好把它拆分开来。在某些时刻,这种策略会让组织架构稳定,并且每个组都能专注于自己的独立业务。

在这篇文章中我们将去评估 PHP 能带我们走多远,以及 Go 能解决哪些我们将会遇到的问题。

PHP 和 微服务

作为一名 PHP 工程师,你应该知道如果在一个庞大的项目中一个网络请求的初始化时间只需要 30 毫秒内,这样就很棒了。再加上 50-100 毫秒的时间交给业务去处理,这样应用的响应时间就会很可观。

Symphony 翻译于 1个月前

直到我们打算打破我们原有的复杂项目,我们坚持为我们的服务提供相同的设置,那将会发生什么? 让我们简单的计算一下,如果服务在相同的请求期间互相交互 10 次,我们就需要 300ms 的请求时间。 这将会是多么糟糕的用户体验!

虽然 PHP 在 WEB 开发方面表现出色,但它在微服务体系结构中的功能还不成熟。 PHP 工程师通常不熟悉诸如超时处理,健康检查,度量收集,隔壁,断路器等基本术语。 他们中的大多数可以在许多其他语言框架中找到。 即使存在的话,在 PHP 生态系统中支持它们也是非常糟糕的。

遇见 Go

来自 Wikipedia 百科:

Go (通常称为golang) 是 Robert Griesemer,Rob Pike 和 Ken Thompson 于 2007 年在 Google 开发的一种开源编程语言。 主要为系统编程而设计,它是 C 和 C ++ 传统的静态类型编译语言,增加了垃圾收集,各种安全功能和 CSP 风格的并发编程功能。

Ellison 翻译于 1个月前

Go 是由谷歌公司开发的一种编程语言,她 (Go语言) 不是一个有趣的 20% 的项目,也不是为了实现他人无法完成的事情,她是为了解决庞大团队编码的复杂性问题应运而生的,解决了他们使用大型的功能集的语言来编写大型软件的困惑。

尽管她具有诸如容易并发和编译快速等优秀特性,但是她最主要的特性是特别的简单,便于开发。有相关的资料中显示,Go 的 关键字 仅仅有 25 个,而在在php中 关键字 有 67 个。

Go 语言的推出大致是在 PHP 语言支持命名空间的时间,也就是大约在 2009 年。在短短的 6 年时间里,已经有包括  Docker, Kubernetes, etcd, InfluxDB 等数十个伟大的项目,不但如此,像 Google,,Dropbox, SoundCloud,Twitter,PayPal 等公司都用 Go 语言构建了他们的后端系统。

shijf 翻译于 1个月前

返回微服务

让我们回过头来看一下之前讨论过的问题,我们可以从使用 Go 语言获得哪些有益的收获。

Go 语言构建的应用可以很快的编译为机器码,许多编程人员感叹道,Go 语言编译的时间非常的快,当他们切换到浏览器变点击「刷新」是,应用程序就已经重新编译了和重新启动了,并且发出了请求。即使是在构建非常大的代码库时,就像是使用一种像 PHP 这种解释型的语言的感觉。

在编写传统的 API 「Hello World」的时候,用十行代码,响应的时间不到 1 毫秒。Go 语言的多核功能可以让编程人员能够运行沉重的软件。生态系统允许选择任何的传输协议,例如 JSON over HTTPgRPC, Protocol Buffers 或者 Thrift。请求很容易在  Zipkin 找到。指标从 statsd 导出到  Prometheus。使用限速器强制进入或外出的请求吞吐量,并保护与断路器的客户服务通信。

shijf 翻译于 1个月前

关于 Go

语言

Go 是一门静态类型的语言, 你需要在初始化变量时声明它的变量类型:

var name string = "golang"

变量可以推断出右侧值的类型。上述代码等同于下列缩写版本。

var name = "golang"

// 更优雅点:

name := "golang"

现在,让我们回想一下在 PHP 中如何交换两个变量的值:

<?php

$buffer = $first;
$first = $second;
$second = $buffer;

Go 的版本:

first, second = second, first

因为 Go 有多重返回值的特性。下列是多重返回值函数的例子:

func getName() (string, string) {
    return "hello", "world"
}

first, last = getName()
Symphony 翻译于 1个月前

在 Go 代码中,你不会看到如此常用的foreachwhile和 do-while 。他们统一成一个单一的 for 声明:

// foreach ($bookings as $key => $booking) {}
for key, booking := range bookings {}

// for ($i = 0; $i < count($bookings); $i++) {}
for i := 0; i < len(bookings); i++ {}

// while ($i < count($bookings)) {}
for i < len(bookings) {}

// do {} while (true);
for {}

虽然 Go 没有称为「类」或「对象」的东西,但其确实具有与集成代码和行为的数据结构的相同定义相匹配的类型。在 Go 中,这被称为「结构体」。我们用一个例子来说明它:

type rect struct { // 定义一个结构体
    width  int
    height int
}

func (r *rect) area() int { // 在结构体上添加方法
    return r.width * r.height
}

r := rect{width: 10, height: 15} // 初始化
fmt.Print(r.area())

有时候定义一个复杂的结构体也是有用的。这里是一个例子:

type Employee struct {
    Name string
    Job  Job
}

type Job struct {
    Employer string
    Position string
}

// 并去结构化它
e := Employee{
    Name: "Sobit",
    Job: {
        Employer: "GetYourGuide",
        Position: "Software Engineer",
    },
}

我渴望谈论其他许多功能,但是这会让我复制官方网站上的 实效 GO 编程  文档,并生成一篇永无止境的文章。但我想花一点时间向您介绍 Go 中的并发,我发现它是该语言最有趣的主题之一。在我们加入之前,你需要知道在 Go 中关于并发的两件事- goroutines 和 channels

Openset 翻译于 2周前

A goroutine has a simple model: it is a function executing concurrently with other goroutines in the same address space. When the call completes, the goroutine exists, silently. Simplest examples is to create a heartbeat function that will print the "I'm alive" message to the terminal every second:

func heartbeat() {
    for {
        time.Sleep(time.Second)
        fmt.Println("I'm still running...")
    }
}

Now, how do we run it so that it executes in the background and allows us to do other things in parallel? The answer is easier than you might think of, just prefix the call with go:

go heartbeat()

// keep doing other stuff

The approach is similar to "fire-and-forget" events triggering. But what if we don't need to forget and are interested in the result the function produces? This is where channels come to play:

func getName(id int, c chan string) {
    c <- someHeavyOperationToFindTheName(id)
}

func main() {
    c := make(chan string, 2) // allocate a channel

    go getName(1, c) // trigger
    go getName(2, c) // don't wait and trigger again

    // keep doing other stuff

    fmt.Printf("Employees: %s, %s", <-c, <-c) // combine
}

To summarize, we just triggered the same function twice and let the application execute them in parallel, and asked to give us back the results at the point where we actually needed them.

Tools

Go was designed, again, with the simplicity in mind. Authors took a rather radical approach to solve common activities engineers do all day long. Say "Goodbye" to the endless "space-vs-tab" battles, code standards from community groups who are trying to somehow simplify the way engineers share code. Go brings the go fmt tool out of the box which takes care of styling your code. No more sharing of IDE configuration files, no more attempts to remember if the opening brace should go on the same or on the next line.

The documentation of the package source can be read using go doc, while go vet will help finding potential problems in the code. Installing vendor libraries is as easy as running go get [github.com/[vendor]/[package](http://github.com/[vendor]/[package)], and tests are executed by triggering go test [package] command. As you can see, most of the tools that engineers include to every application in every language is already here, out of the box.

Deployment

Deployment is a mandatory action no matter which language you choose or what you're building. Being a PHP engineer, how many Capistrano or Envoyconfigurations have you written in your professional life? How many manually changed files have you transferred over FTP to your hosting provider back in the days?

This is how the most common and simple PHP deployment process looks like:

  • Checkout the latest code on the target server into a new release folder
  • Copy cached dependencies and install updated ones
  • Copy environment-specific configuration files
  • Run all the scripts to warm the application up
  • Point the current release symlink into the new release folder
  • Restart PHP-FPM

Some teams can take this process into a more advanced level like:

  • Checkout the latest code on the build server
  • "Build" it (install dependencies, warm the caches up, etc.)
  • Create a distributable "artifact" (an archived tar.gz file)
  • Transfer the artifact to the target server
  • Unarchive into a new release folder
  • Point the current release symlink into the new release folder
  • Restart PHP-FPM

Of course, besides that you need to make sure your target and build servers have at least PHP-FPM and PHP installed, and they better match their versions between each other as well as the version engineers use for local development.

And now let me introduce the deployment process of a regular Go application:

  • Checkout the latest code on the build server
  • Build it (note the absence of quotes)
  • Transfer the artifact (again no quotes) to the target server
  • Restart the running application

And that's it. The only difference between potentially simple and advanced versions is whether to have a standalone build server for that or not.

The beauty is that you don't even need to have Go installed on your target servers, and even if they are running different operating systems or based on different CPU architectures, you can still prepare artifacts for all of them (even for Windows) from a single build server or any other machine.

Conclusion

It was never recommended to decompose a system into microservices while it is not mature enough. While small, a business has to be flexible and react quickly to the opportunities in the market. This is not an ideal environment for building microservices, and more benefits can be achieved by having a monolith instead. PHP with its ecosystem perfectly fits into this strategy.

When the organization stabilizes and it is easy to identify its bounded contexts, building microservices in PHP to complement them may be painful. Various tools and techniques exist in many other languages to support such architecture. You may put yourself into risk to either build your own tools or refuse them completely - both can be costly for your organization.

On the other hand, building microservices in Go is worth considering. The language is easy to write and understand, its learning curve is not that steep as with Java or Scala, and the performance is not far behind C. The compilation time keeps engineers efficient, while the support for multi-core or networked machines makes it possible to write powerful applications.

Additional resources

The best place to land for a new gopher is probably the learning section on the official website. It includes an interactive introduction to Go to try it out in your browser as well as the best practices document that will help understanding how to write clear, idiomatic Go code.

If that feels not enough, there's a collection of community-driven initiatives to help sharpening newly acquired skills.

If you're the same fan of JetBrains IDEs as I am, check out the excellent Go plugin for IntelliJ, which is developed mostly by the same JetBrains developers. It can be installed on almost any of their IDEs, including PhpStorm. For other IDEs and text editors, visit wiki page.

When you feel like ready to build your first production-ready microservice in Go, I would encourage you to look at Go kit. It is a programming toolkit that strives to solve common problems in distributed systems to let engineers focus on the business logic.

Least important, but worth mentioning, is the possibility to build client side JavaScript applications using GopherJS and entirely native or SDK applications for iOS and Android.

原文地址:http://sobit.me/2016/02/25/go-from-php-e...

译文地址:https://golangcaff.com/topics/21/from-a-...


本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

本帖已被设为精华帖!
回复数量: 2
  • xusenlin
    1个月前

    很好的文章。

  • an0nym0us
    4周前

    Go 的 关键字 仅仅有 25 个,而在在php中 关键字 有 67 个
    这俩关键词的链接反了

暂无评论~~
您需要登陆以后才能留下评论!

Go Web 编程

Go 编程基础(视频教程)

Go 入门指南