这两年唱衰 PHP 的论调不少(其实我觉得大可不必),导致不少 PHP 程序员产生危机感,纷纷寻求转型,根据我的观察,基本上 Go 都是首选。不管怎么说,技多不压身,多掌握一点知识总是好的。本文就作为一个基础的入门来帮助 PHP 程序员入门 Go 语言吧。

1. 脚本语言 vs 编译型语言

这其实是个我每次面试都会问的问题,脚本语言和编译型语言有什么区别。维基上的解释:

  • 语法和结构通常比较简单
  • 学习和使用通常比较简单
  • 通常以容易修改程序的“解释”作为运行方式,而不需要“编译”
  • 程序的开发产能优于运行性能

从我的角度,可以从执行角度和环境依赖上来说。

简单理解,作为脚本语言,你可以单独写一行 <?php echo "Hello World";,命名为任意文件,然后使用 php 解释器来执行。甚至可以使用 php -a 进入交互环境执行任何代码。

go 这种编译型语言就不是这样。因为是先编译后执行,go 一定需要知道程序的入口文件和入口函数。所以一个程序的执行一定需要 main 函数(go test 文件除外)。虽然 go 也提供了 run 指令省略到编译的步骤。

在环境依赖上,执行 php 的服务器一定需要预装固定版本 php 解释器,而编译成二进制文件的 go 程序则只需要在对应架构的服务器上即可运行。这本质上是 php 的解释器扮演的才是 go 编译后的程序的角色,而脚本则是在 php 解释器构建的一层虚拟机上执行的。所以脚本语言在不同平台上表现的一致性更好,而使用编译型语言则需要有更好的操作系统和网络底层知识。

2. 动态语言 vs 静态语言

动态语言与静态语言又分别被称为弱类型语言和强类型语言,其实这样描述也更加形象。

PHP 会在执行的过程中做隐式类型转换(虽然也提供了类型转换的函数和关键字),go 的类型转换却需要手动、强制的来执行。

弱类型语言带来了很多便利性,但是也隐含了很多问题,以至于 PHP 要引入 === 这种比较方式,不过经验丰富的 PHP 开发应该是能在每一个变量定义之前都确认好它的数据类型的。go 语言中不存在隐式转换的问题,但是写起来肯定也没有那么爽,光是 int 都有多种长度的类型,会让很多新手不太适应,同样的道理,定义每一个变量之前都稍加思考,就能轻松解决这个问题。

go 提供了 :=var 关键字的赋值方式,编译器会根据初始化的值自动推导出相应的类型,但是这个用法同样也要求你小心处理作用域的问题,不妨猜一下下面这段代码的输出:

package main

import (
    "fmt"
)

func main() {
    var a int
    a = 1

    if a, ok := foo(); ok == true {
        fmt.Println(a)
    }
    fmt.Println(a)

    var ok bool
    if a, ok = foo(); ok == true {
        fmt.Println(a)
    }
    fmt.Println(a)
}

func foo() (int, bool) {
    return 2, true
}

3. Go 还要不要 MVC

先说我的观点:不需要。其实不只是 go 开发,PHP 的微服务框架比如 Slim 默认也不是按照 MVC 的方式组织代码的。本身现在前端工程化程度越来越高,一般都拉出去单独开项目,也不需要接口项目准备 V 的部分,所以说 MVC 是时代的产物,可以被淘汰了。

再者,go 使用的函数名、变量一般都比较简洁,Controller 这个长长的单词看起来真的有点突兀。

go 语言本身有一些约定性的命名方式,对代码的访问、编译和执行都是有影响的,比如 internal 目录下的内容不能被外部包访问,在搭建 go 项目的时候,也应该按照这些约定来,这才符合 go 的规范。

这里有一个 go 项目目录组织的 demo:https://github.com/golang-standards/project-layout, 值得参考一下。也可以看一下这篇文章,写的很不错:https://draveness.me/golang-101/

4. Go 还要不要框架

既然 MVC 都不需要了,那开发框架还需不需要呢?这个问题没有固定答案,因为同样在 PHP 中,框架的概念也渐渐弱化,包的概念逐渐强化。只要有 Composer,徒手搭建一个 PHP 的框架不是什么难事。

1.13 的版本之后,go 终于有了默认统一的包管理方式,虽然不算完美,但总算解决了以前管理混乱、限制太多的问题,具体的介绍可以参考官方说明:https://blog.golang.org/using-go-modules

选一个或者写一个好用的基础结构,配上一些不错的包,就可以愉快的开始项目开发了。

最后我还是想说明一下,语言本身可能有设计上的不同,但不应该有好坏之分,特别是应用比较广泛的语言,自然是因为其自身的某些特性吸引人。选择适合自己的、适合业务的就可以,不要当语言上的精神贵族。