第二章:基础语法——Go与PHP的核心差异

这一章我们将快速过一遍Go的基础语法,并重点关注与PHP的不同之处,帮助你重塑编码习惯。

2.1 变量与常量 #

Go是静态类型语言,这意味着你一旦声明了变量的类型,就不能再赋给它其他类型的值。这与PHP的动态类型形成鲜明对比。

package main

import "fmt"

func main() {
    // === 变量声明 ===

    // 方式一:标准声明,先声明类型,再赋值 (默认值为零值,如int为0, string为"")
    var name string
    name = "Go Lang"
    // var name string = "Go Lang" // 也可以合并

    // 方式二:类型推导,Go会根据值自动推断类型
    var age = 30 // age被推断为int类型

    // 方式三:短变量声明 (最常用),只能在函数内部使用
    // := 会自动声明并初始化变量
    isDeveloper := true // isDeveloper被推断为bool类型

    fmt.Println(name, age, isDeveloper)

    // --- PHP对比 ---
    // $name = "PHP";
    // $age = 25;
    // $isDeveloper = true;
    // $name = 123; // 在PHP中这是允许的,但在Go中会编译错误

    // === 常量 ===
    const PI = 3.14159
    // PI = 3.14 // 尝试修改常量会导致编译错误

    // --- PHP对比 ---
    // define('PI', 3.14159);
    // const PI = 3.14159;
}

核心差异小结

  • 静态类型:Go在编译时检查类型,更安全。PHP在运行时检查,更灵活但易出错。
  • 声明方式:Go使用var:=,而PHP使用$
  • 零值:Go中声明但未赋值的变量都有一个明确的“零值”(0, false, "", nil等),避免了PHP中undefined variable的警告。

2.2 数据类型 #

Go拥有丰富的基础数据类型。

  • 布尔型: bool (true, false)
  • 字符串: string (Go的字符串是不可变的)
  • 整型: int, int8, int16, int32, int64, uint (无符号) …
    • int的长度取决于操作系统(32位或64位)。
  • 浮点型: float32, float64
  • 其他: byte (uint8的别名), rune (int32的别名,代表一个Unicode码点)

2.3 控制结构 #

Go的控制结构更简洁,尤其体现在循环上。

If-Else #

if语句的条件不需要用括号()包围。

func main() {
    score := 85
    if score >= 90 {
        fmt.Println("Excellent")
    } else if score >= 60 {
        fmt.Println("Pass")
    } else {
        fmt.Println("Fail")
    }

    // if语句可以有一个简短的初始化语句
    if num := 9; num < 10 {
        fmt.Println("Number is less than 10")
    }
}

For 循环 #

Go只有一个循环关键字:for。但它能实现PHP中for, while, foreach的所有功能。

func main() {
    // 1. 标准for循环 (类似PHP的for)
    for i := 0; i < 5; i++ {
        fmt.Println(i)
    }

    // 2. "while"循环
    // 初始化和后置语句都是可选的
    sum := 1
    for sum < 100 { // 这就等价于 while(sum < 100)
        sum += sum
    }
    fmt.Println(sum)

    // 3. "foreach"循环 (使用 range)
    // 这是遍历数组、切片、map等数据结构的方式
    langs := []string{"PHP", "Go", "JavaScript"}
    for index, value := range langs {
        fmt.Printf("Index: %d, Value: %s\n", index, value)
    }
    // 如果你不需要索引,可以用下划线_忽略
    for _, value := range langs {
        fmt.Println(value)
    }

    // 4. 无限循环
    // for {
    //     // ...
    // }
}

Switch #

Go的switch语句比PHP的更强大、更安全。

  • 默认break:每个case执行完毕后会自动终止,不需要显式写break
  • fallthrough关键字:如果你确实需要像PHP那样继续执行下一个case,可以使用fallthrough关键字。
  • 条件可以是任意类型switch后面可以不带表达式,然后在case里写判断条件。
func main() {
    lang := "Go"
    switch lang {
    case "PHP":
        fmt.Println("A dynamic language.")
    case "Go":
        fmt.Println("A static, compiled language.") // 执行到这里就结束了
    default:
        fmt.Println("Another language.")
    }

    // 无表达式的switch,更像if-else链
    score := 95
    switch {
    case score >= 90:
        fmt.Println("Excellent")
    case score >= 60:
        fmt.Println("Pass")
    default:
        fmt.Println("Fail")
    }
}

2.4 函数 #

Go的函数支持多返回值,这是一个非常有用的特性,常用于同时返回结果和错误。

package main

import (
    "fmt"
    "errors"
)

// 函数定义: func 函数名(参数列表) (返回值列表) { ... }
func add(a int, b int) int {
    return a + b
}

// 参数类型相同时,可以简写
func multiply(a, b int) int {
    return a * b
}

// 多返回值函数
func divide(a, b float64) (float64, error) {
    if b == 0 {
        // errors.New创建一个新的error类型的值
        return 0, errors.New("division by zero")
    }
    return a / b, nil // nil是Go中error类型的零值,表示没有错误
}

func main() {
    result := add(10, 20)
    fmt.Println("10 + 20 =", result)

    // 调用多返回值函数
    quotient, err := divide(10, 2)
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("10 / 2 =", quotient)
    }

    quotient, err = divide(10, 0)
    if err != nil {
        fmt.Println("Error:", err) // Error: division by zero
    } else {
        fmt.Println("10 / 0 =", quotient)
    }
}

与PHP的对比:

  • 多返回值: Go原生支持,这是处理错误的常用模式。PHP 7.1+虽然可以通过数组解构模拟,但Go的实现更原生、类型更安全。
  • 错误处理: Go倾向于将error作为一个返回值,由调用者显式处理。PHP则更常用try-catch异常机制。我们将在后面章节深入探讨。