这一章我们将快速过一遍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
异常机制。我们将在后面章节深入探讨。