普通视图

发现新文章,点击刷新页面。
昨天 — 2026年4月1日首页

前端转后端基础- 变量和类型

2026年4月1日 20:38

PHP、Go、JavaScript三种语言在变量和类型相关的核心语法对照。

一、变量声明和赋值

PHP 变量语法

<?php
// PHP变量以$符号开头
$name = "张三";
$age = 25;
$height = 175.5;
$isStudent = true;
$score = null;

// 变量命名规则
$firstName = "李";           // 驼峰命名
$last_name = "四";           // 下划线命名
$UserName = "admin";         // 大驼峰命名
$_privateVar = "secret";     // 私有变量
$MAX_VALUE = 100;            // 常量风格

// 动态类型 - 变量类型可以改变
$var = 10;                   // 整数
$var = "hello";              // 字符串
$var = 3.14;                 // 浮点数
$var = [1, 2, 3];            // 数组
$var = new stdClass();       // 对象

// 引用赋值
$a = 5;
$b = &$a;                    // $b是$a的引用
$b = 10;
echo $a;                     // 输出10,$a的值也被改变了

// 可变变量
$varName = "name";
$$varName = "王五";          // 相当于 $name = "王五"
echo $name;                  // 输出"王五"

// 变量解析
$greeting = "Hello";
$message = "$greeting World";    // 双引号中变量会被解析
$message2 = '$greeting World';   // 单引号中变量不会被解析

// 变量变量
$prefix = "user";
${$prefix . "_name"} = "赵六";   // 相当于 $user_name = "赵六"
echo $user_name;                 // 输出"赵六"

// 变量作用域
$globalVar = "全局变量";

function testScope() {
    global $globalVar;           // 使用global关键字访问全局变量
    $localVar = "局部变量";
    echo $globalVar;
}

// 静态变量
function counter() {
    static $count = 0;
    $count++;
    return $count;
}

echo counter();  // 1
echo counter();  // 2
echo counter();  // 3

// 变量销毁
$var = "test";
unset($var);                     // 销毁变量
// echo $var;                    // 会报错:未定义变量

// 变量存在性检查
$var = "exists";
if (isset($var)) {
    echo "变量存在";
}

// 变量类型检查
$var = 123;
if (is_int($var)) {
    echo "是整数";
}

// 变量输出
$var = "test";
echo $var;                       // 直接输出
print $var;                      // print函数输出
var_dump($var);                  // 输出变量类型和值
print_r($var);                   // 打印变量信息

// 变量插值
$name = "张三";
$age = 25;
echo "姓名:$name,年龄:$age";
echo "姓名:{$name},年龄:{$age}";

// 变量赋值运算符
$a = 10;
$a += 5;     // $a = $a + 5
$a -= 3;     // $a = $a - 3
$a *= 2;     // $a = $a * 2
$a /= 4;     // $a = $a / 4
$a %= 3;     // $a = $a % 3
$a .= "test"; // $a = $a . "test" (字符串连接)

// 递增递减运算符
$i = 0;
$i++;        // 后置递增
++$i;        // 前置递增
$i--;        // 后置递减
--$i;        // 前置递减

// 三元运算符
$age = 20;
$status = ($age >= 18) ? "成人" : "未成年";

// 空合并运算符
$username = $_GET['user'] ?? 'guest';

// 变量类型声明(PHP 7+)
function add(int $a, int $b): int {
    return $a + $b;
}

// 严格类型模式
declare(strict_types=1);

// 变量变量的高级用法
$var1 = "value1";
$var2 = "var1";
echo $$var2;  // 输出"value1"

// 变量引用的高级用法
function modifyByRef(&$param) {
    $param = "modified";
}

$value = "original";
modifyByRef($value);
echo $value;  // 输出"modified"
?>

Go 变量语法

package main

import (
    "fmt"
    "reflect"
)

func main() {
    // 基本变量声明
    var name string = "张三"
    var age int = 25
    var height float64 = 175.5
    var isStudent bool = true
    var score *int = nil
    
    // 简短声明
    firstName := "李"
    lastName := "四"
    userName := "admin"
    
    // 多变量声明
    var (
        city string = "北京"
        population int = 21540000
        area float64 = 16410.54
    )
    
    // 多变量同时赋值
    a, b, c := 1, 2, 3
    x, y := "hello", 3.14
    
    // 变量类型推断
    var inferred = "自动推断类型"  // 推断为string
    inferred2 := 123               // 推断为int
    
    // 常量声明
    const (
        PI = 3.14159
        MAX_SIZE = 100
        DEFAULT_NAME = "guest"
    )
    
    // 枚举常量
    const (
        Sunday = iota
        Monday
        Tuesday
        Wednesday
        Thursday
        Friday
        Saturday
    )
    
    // 类型别名
    type Celsius float64
    type Fahrenheit float64
    
    var temperature Celsius = 25.5
    
    // 指针变量
    var ptr *int
    num := 10
    ptr = &num
    fmt.Println(*ptr)  // 解引用
    
    // 数组变量
    var arr [3]int = [3]int{1, 2, 3}
    arr2 := [5]string{"a", "b", "c", "d", "e"}
    
    // 切片变量
    slice := []int{1, 2, 3, 4, 5}
    slice2 := make([]string, 3)
    
    // 映射变量
    m := make(map[string]int)
    m["age"] = 25
    m["score"] = 90
    
    // 结构体变量
    type Person struct {
        Name string
        Age  int
    }
    
    var p Person
    p.Name = "张三"
    p.Age = 25
    
    p2 := Person{Name: "李四", Age: 30}
    
    // 接口变量
    var i interface{}
    i = "hello"
    i = 123
    i = 3.14
    
    // 通道变量
    ch := make(chan int)
    
    // 函数变量
    var add func(int, int) int
    add = func(a, b int) int {
        return a + b
    }
    
    // 变量作用域
    globalVar := "全局作用域"
    
    {
        localVar := "块级作用域"
        fmt.Println(localVar)
    }
    
    // 变量遮蔽
    outer := "outer"
    {
        outer := "inner"  // 遮蔽外层变量
        fmt.Println(outer)  // 输出"inner"
    }
    fmt.Println(outer)  // 输出"outer"
    
    // 变量零值
    var zeroInt int      // 0
    var zeroString string // ""
    var zeroBool bool    // false
    var zeroPtr *int     // nil
    
    // 变量类型转换
    var i1 int = 10
    var f1 float64 = float64(i1)
    var i2 int = int(f1)
    
    // 变量地址和指针
    value := 42
    ptrValue := &value
    fmt.Printf("值: %d, 地址: %p\n", value, ptrValue)
    
    // 变量比较
    str1 := "hello"
    str2 := "hello"
    fmt.Println(str1 == str2)  // true
    
    // 变量打印
    fmt.Println(name, age, height)
    fmt.Printf("姓名: %s, 年龄: %d\n", name, age)
    fmt.Printf("类型: %T, 值: %v\n", name, name)
    
    // 反射获取变量信息
    varName := "test"
    fmt.Println("类型:", reflect.TypeOf(varName))
    fmt.Println("值:", reflect.ValueOf(varName))
    
    // 变量交换
    x1, y1 := 1, 2
    x1, y1 = y1, x1  // 交换值
    
    // 变量初始化
    var initialized string
    initialized = "已初始化"
    
    // 多返回值
    result1, result2 := multipleReturn()
    fmt.Println(result1, result2)
    
    // 匿名变量
    _, nameOnly := getNameAndAge()
    fmt.Println(nameOnly)
    
    // 变量可见性
    // 首字母大写:包外可见
    // 首字母小写:包内可见
    
    // 变量命名规范
    // 使用驼峰命名法
    // 首字母大写表示导出
    // 首字母小写表示私有
    
    // 变量注释
    // 单行注释
    /* 
       多行注释
    */
    
    // 变量文档注释
    // ExportedVar 是一个导出的变量
    var ExportedVar = "exported"
}

// 多返回值函数
func multipleReturn() (int, string) {
    return 1, "hello"
}

// 返回多个值的函数
func getNameAndAge() (string, int) {
    return "张三", 25
}

JavaScript 变量语法

// var 声明(函数作用域)
var name = "张三";
var age = 25;
var height = 175.5;
var isStudent = true;
var score = null;
var undefinedVar;

// let 声明(块级作用域)
let firstName = "李";
let lastName = "四";
let userName = "admin";

// const 声明(常量)
const PI = 3.14159;
const MAX_SIZE = 100;
const DEFAULT_NAME = "guest";

// 变量提升
console.log(hoistedVar);  // undefined
var hoistedVar = "提升";

// 暂时性死区
// console.log(tempDead);  // ReferenceError
let tempDead = "暂时性死区";

// 重复声明
var x = 1;
var x = 2;  // 允许
// let y = 1;
// let y = 2;  // SyntaxError: Identifier 'y' has already been declared

// 变量作用域
var globalVar = "全局变量";

function testScope() {
    var functionVar = "函数作用域";
    let blockVar = "块级作用域";
    
    if (true) {
        var ifVar = "if块中的var";
        let ifLetVar = "if块中的let";
    }
    
    console.log(ifVar);     // 可访问
    // console.log(ifLetVar); // ReferenceError
}

// 块级作用域
{
    let blockScoped = "块级作用域变量";
    const blockConst = "块级常量";
}
// console.log(blockScoped);  // ReferenceError

// 变量解构赋值
// 数组解构
let [a, b, c] = [1, 2, 3];
let [first, , third] = [1, 2, 3];  // 跳过第二个元素
let [head, ...tail] = [1, 2, 3, 4, 5];  // rest操作符

// 对象解构
let {name: n, age: a} = {name: "张三", age: 25};
let {city = "北京"} = {};  // 默认值

// 嵌套解构
let {user: {name: userName}} = {user: {name: "李四"}};

// 交换变量
let x1 = 1, y1 = 2;
[x1, y1] = [y1, x1];

// 多返回值解构
function multipleReturn() {
    return [1, "hello", true];
}
let [num, str, bool] = multipleReturn();

// 变量类型
let str = "字符串";
let num = 123;
let float = 3.14;
let bool = true;
let n = null;
let undef = undefined;
let sym = Symbol("unique");
let bigInt = 123n;

// 动态类型
let dynamic = 10;
dynamic = "hello";
dynamic = true;
dynamic = [1, 2, 3];
dynamic = {key: "value"};

// typeof 运算符
console.log(typeof str);      // "string"
console.log(typeof num);      // "number"
console.log(typeof bool);     // "boolean"
console.log(typeof n);        // "object"
console.log(typeof undef);    // "undefined"
console.log(typeof sym);      // "symbol"
console.log(typeof bigInt);   // "bigint"

// 类型转换
// 字符串转换
let strNum = String(123);
let strBool = String(true);
let strNull = String(null);

// 数字转换
let numStr = Number("123");
let numBool = Number(true);
let numParse = parseInt("123");
let floatParse = parseFloat("3.14");

// 布尔转换
let boolStr = Boolean("hello");
let boolNum = Boolean(0);
let boolArr = Boolean([]);

// 隐式类型转换
let result = "5" + 3;      // "53"
let result2 = "5" - 3;     // 2
let result3 = "5" * 3;     // 15

// 变量比较
console.log(5 == "5");      // true (宽松相等)
console.log(5 === "5");     // false (严格相等)
console.log(null == undefined);  // true
console.log(null === undefined); // false

// 变量运算符
let count = 0;
count++;      // 后置递增
++count;      // 前置递增
count--;      // 后置递减
--count;      // 前置递减

count += 5;   // count = count + 5
count -= 3;   // count = count - 3
count *= 2;   // count = count * 2
count /= 4;   // count = count / 4
count %= 3;   // count = count % 3

// 三元运算符
let age = 20;
let status = (age >= 18) ? "成人" : "未成年";

// 逻辑运算符
let andResult = true && "hello";  // "hello"
let orResult = false || "default"; // "default"
let nullish = null ?? "default";  // "default"

// 可选链操作符
let user = {name: "张三"};
let city = user?.address?.city;  // undefined,不会报错

// 空值合并运算符
let username = null ?? "guest";  // "guest"

// 模板字符串
let name = "张三";
let age = 25;
let message = `姓名:${name},年龄:${age}`;
let multiLine = `
    这是
    多行
    字符串
`;

// 变量属性访问
let obj = {key: "value"};
let keyName = "key";
console.log(obj.key);        // 点号访问
console.log(obj["key"]);     // 方括号访问
console.log(obj[keyName]);   // 动态属性名

// 变量方法调用
let str = "hello";
console.log(str.toUpperCase());  // "HELLO"
console.log(str.length);         // 5

// 变量作为函数参数
function greet(name) {
    console.log(`Hello, ${name}!`);
}
greet("张三");

// 变量作为函数返回值
function createPerson(name, age) {
    return {name, age};
}
let person = createPerson("李四", 30);

// 闭包中的变量
function outer() {
    let outerVar = "outer";
    return function inner() {
        console.log(outerVar);
    };
}
let closure = outer();
closure();  // "outer"

// 立即执行函数表达式中的变量
(function() {
    let iifeVar = "IIFE";
    console.log(iifeVar);
})();

// 变量垃圾回收
let largeData = new Array(1000000).fill(0);
largeData = null;  // 允许垃圾回收

// 变量冻结
const obj = {key: "value"};
Object.freeze(obj);
// obj.key = "new";  // 严格模式下会报错

// 变量密封
const sealed = {key: "value"};
Object.seal(sealed);
// sealed.newKey = "new";  // 严格模式下会报错

// 变量属性描述符
let descriptorObj = {};
Object.defineProperty(descriptorObj, 'readOnly', {
    value: "只读",
    writable: false,
    enumerable: true,
    configurable: false
});

// 变量代理
let target = {key: "value"};
let proxy = new Proxy(target, {
    get: function(obj, prop) {
        return prop in obj ? obj[prop] : "默认值";
    }
});

// 变量符号
let sym1 = Symbol("description");
let sym2 = Symbol("description");
console.log(sym1 === sym2);  // false

// 全局符号注册表
let globalSym = Symbol.for("global");
let sameSym = Symbol.for("global");
console.log(globalSym === sameSym);  // true

// 变量迭代
let iterable = [1, 2, 3];
for (let item of iterable) {
    console.log(item);
}

// 变量展开运算符
let arr1 = [1, 2, 3];
let arr2 = [...arr1, 4, 5];
let obj1 = {a: 1, b: 2};
let obj2 = {...obj1, c: 3};

// 变量剩余参数
function sum(...numbers) {
    return numbers.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3, 4, 5));  // 15

// 变量标签模板
function tag(strings, ...values) {
    console.log(strings);
    console.log(values);
}
let name = "张三";
tag`Hello ${name}!`;

// 变量私有字段(ES2022+)
class MyClass {
    #privateField = "私有字段";
    getPrivate() {
        return this.#privateField;
    }
}

// 变量静态字段
class MyClass2 {
    static staticField = "静态字段";
}
console.log(MyClass2.staticField);

// 变量装饰器(实验性)
// @decorator
// class DecoratedClass {
//     @readonly
//     method() {}
// }

二、数据类型详解

PHP 数据类型

<?php
// 标量类型
// 整数类型
$int1 = 123;              // 十进制
$int2 = -123;             // 负数
$int3 = 0123;             // 八进制(123)
$int4 = 0x1A;             // 十六进制(26)
$int5 = 0b11111111;       // 二进制(255)

// 浮点数类型
$float1 = 1.234;
$float2 = 1.2e3;          // 1200
$float3 = 7E-10;          // 0.0000000007

// 字符串类型
$string1 = '单引号字符串';
$string2 = "双引号字符串,可以包含变量 $name";
$string3 = "转义字符:\n 换行,\t 制表符";
$string4 = <<<EOT
    多行字符串
    Heredoc语法
EOT;

// 布尔类型
$bool1 = true;
$bool2 = false;
$bool3 = (bool)1;         // true
$bool4 = (bool)0;         // false
$bool5 = (bool)"0";       // false
$bool6 = (bool)"";        // false
$bool7 = (bool)null;      // false

// 复合类型
// 数组类型
$array1 = array(1, 2, 3);          // 索引数组
$array2 = [1, 2, 3];               // 短数组语法
$array3 = ["a" => 1, "b" => 2];    // 关联数组
$array4 = [1, "a" => 2, 3];        // 混合数组

// 对象类型
class Person {
    public $name;
    public $age;
    
    function __construct($name, $age) {
        $this->name = $name;
        $this->age = $age;
    }
}

$obj = new Person("张三", 25);

// 特殊类型
// NULL类型
$null1 = null;
$null2 = NULL;
$null3;  // 未初始化的变量

// 资源类型
$file = fopen("test.txt", "r");
// $file 是一个资源类型

// 回调类型
function callback($param) {
    echo $param;
}
$cb = 'callback';
$cb("test");

// 类型声明
// 标量类型声明(PHP 7+)
function add(int $a, int $b): int {
    return $a + $b;
}

function divide(float $a, float $b): float {
    return $a / $b;
}

function greet(string $name): string {
    return "Hello, $name";
}

function isActive(bool $status): bool {
    return $status;
}

// 返回类型声明
function getArray(): array {
    return [1, 2, 3];
}

function getObject(): Person {
    return new Person("李四", 30);
}

function getCallable(): callable {
    return function() {
        return "callable";
    };
}

// 可空类型
function nullable(?string $name): ?string {
    return $name;
}

// 联合类型(PHP 8+)
function union(int|string $param): int|string {
    return $param;
}

// 交集类型(PHP 8.1+)
function intersection(Traversable&Countable $param) {
    // ...
}

// 类型检查函数
$var = 123;
var_dump(is_int($var));        // true
var_dump(is_float($var));      // false
var_dump(is_string($var));     // false
var_dump(is_bool($var));       // false
var_dump(is_array($var));      // false
var_dump(is_object($var));     // false
var_dump(is_null($var));       // false
var_dump(is_numeric($var));    // true
var_dump(is_scalar($var));     // true

// 类型转换
// 显式转换
$int = (int)"123";
$float = (float)"3.14";
$string = (string)123;
$bool = (bool)"true";
$array = (array)$obj;
$object = (object)$array;

// settype函数
$var = "123";
settype($var, "integer");
var_dump($var);  // int(123)

// 类型比较
var_dump(1 == "1");      // true (宽松比较)
var_dump(1 === "1");     // false (严格比较)
var_dump(0 == false);    // true
var_dump(0 === false);   // false
var_dump(null == 0);     // true
var_dump(null === 0);    // false

// 类型提示
class Container {
    private array $items = [];
    
    public function addItem(string $item): void {
        $this->items[] = $item;
    }
    
    public function getItems(): array {
        return $this->items;
    }
}

// 枚举类型(PHP 8.1+)
enum Status: string {
    case DRAFT = 'draft';
    case PUBLISHED = 'published';
    case ARCHIVED = 'archived';
}

$status = Status::PUBLISHED;
echo $status->value;  // "published"

// 只读属性(PHP 8.1+)
class User {
    public readonly string $name;
    
    public function __construct(string $name) {
        $this->name = $name;
    }
}

// 新的初始化器(PHP 8.1+)
class Product {
    public function __construct(
        private string $name,
        private float $price = 0.0,
        private array $tags = []
    ) {}
}

// 属性类型
class Article {
    public string $title;
    public ?string $content = null;
    public array $metadata = [];
    public DateTime $createdAt;
}

// 泛型注释(虽然PHP没有原生泛型)
/**
 * @template T
 * @param T $value
 * @return T
 */
function identity($value) {
    return $value;
}
?>

Go 数据类型

package main

import (
    "fmt"
    "math"
    "math/big"
    "unsafe"
)

func main() {
    // 布尔类型
    var b1 bool = true
    var b2 bool = false
    fmt.Println(b1, b2)
    
    // 数值类型
    // 整数类型
    var int8Var int8 = 127           // -128 to 127
    var int16Var int16 = 32767       // -32768 to 32767
    var int32Var int32 = 2147483647  // -2147483648 to 2147483647
    var int64Var int64 = 9223372036854775807 // -9223372036854775808 to 9223372036854775807
    var intVar int = 42              // 平台相关,32或64位
    
    // 无符号整数
    var uint8Var uint8 = 255         // 0 to 255
    var uint16Var uint16 = 65535     // 0 to 65535
    var uint32Var uint32 = 4294967295 // 0 to 4294967295
    var uint64Var uint64 = 18446744073709551615 // 0 to 18446744073709551615
    var uintVar uint = 42            // 平台相关
    
    // 浮点数类型
    var float32Var float32 = 3.14    // IEEE-754 32位浮点数
    var float64Var float64 = 3.141592653589793 // IEEE-754 64位浮点数
    
    // 复数类型
    var complex64Var complex64 = 1 + 2i
    var complex128Var complex128 = 3 + 4i
    
    // 字符串类型
    var str1 string = "Hello"
    var str2 string = `Raw string
    多行字符串
    不转义`
    
    // 字节和符文
    var byteVar byte = 'A'           // uint8的别名
    var runeVar rune = '中'          // int32的别名,表示Unicode码点
    
    // 派生类型
    // 指针类型
    var ptr *int
    num := 42
    ptr = &num
    fmt.Println(*ptr)
    
    // 数组类型
    var arr1 [3]int = [3]int{1, 2, 3}
    var arr2 = [5]string{"a", "b", "c", "d", "e"}
    var arr3 = [...]int{1, 2, 3, 4, 5}  // 编译器推断长度
    
    // 切片类型
    var slice1 []int = []int{1, 2, 3}
    var slice2 = make([]string, 3)
    var slice3 = make([]float64, 5, 10) // 长度5,容量10
    
    // 映射类型
    var map1 map[string]int = make(map[string]int)
    var map2 = map[string]string{
        "name": "张三",
        "city": "北京",
    }
    
    // 结构体类型
    type Person struct {
        Name string
        Age  int
    }
    var p1 Person
    var p2 = Person{Name: "李四", Age: 30}
    
    // 接口类型
    var i1 interface{}
    i1 = "hello"
    i1 = 123
    i1 = 3.14
    
    // 函数类型
    var add func(int, int) int
    add = func(a, b int) int {
        return a + b
    }
    
    // 通道类型
    var ch1 chan int = make(chan int)
    var ch2 chan string = make(chan string, 10) // 带缓冲的通道
    
    // 类型别名
    type Celsius float64
    type Fahrenheit float64
    
    var temp Celsius = 25.5
    
    // 类型定义
    type MyInt int
    var myInt MyInt = 42
    
    // 枚举类型(使用iota)
    type Weekday int
    
    const (
        Sunday Weekday = iota
        Monday
        Tuesday
        Wednesday
        Thursday
        Friday
        Saturday
    )
    
    // 类型转换
    var i int = 42
    var f float64 = float64(i)
    var j int = int(f)
    
    var b byte = byte(i)
    var r rune = rune(i)
    
    // 类型断言
    var val interface{} = "hello"
    str, ok := val.(string)
    if ok {
        fmt.Println(str)
    }
    
    // 类型开关
    switch v := val.(type) {
    case string:
        fmt.Println("字符串:", v)
    case int:
        fmt.Println("整数:", v)
    default:
        fmt.Println("未知类型")
    }
    
    // 类型大小
    fmt.Println("int8大小:", unsafe.Sizeof(int8Var))
    fmt.Println("int64大小:", unsafe.Sizeof(int64Var))
    fmt.Println("float64大小:", unsafe.Sizeof(float64Var))
    
    // 类型零值
    var zeroInt int      // 0
    var zeroFloat float64 // 0.0
    var zeroBool bool    // false
    var zeroString string // ""
    var zeroPtr *int     // nil
    var zeroSlice []int  // nil
    var zeroMap map[string]int // nil
    var zeroFunc func()  // nil
    var zeroChan chan int // nil
    
    // 常量
    const Pi = 3.14159
    const MaxSize = 100
    
    const (
        A = iota  // 0
        B         // 1
        C         // 2
    )
    
    // 无类型常量
    const untyped = 42  // 无类型整数常量
    const untypedFloat = 3.14  // 无类型浮点数常量
    
    // 类型检查
    var x interface{} = 42
    fmt.Println("类型:", fmt.Sprintf("%T", x))
    fmt.Println("值:", x)
    
    // 大数类型
    bigInt := big.NewInt(12345678901234567890)
    fmt.Println("大整数:", bigInt)
    
    // 位运算
    a := 5  // 101
    b := 3  // 011
    fmt.Println("与:", a & b)   // 001 = 1
    fmt.Println("或:", a | b)   // 111 = 7
    fmt.Println("异或:", a ^ b) // 110 = 6
    fmt.Println("左移:", a << 1) // 1010 = 10
    fmt.Println("右移:", a >> 1) // 10 = 2
    
    // 数学常量
    fmt.Println("最大int8:", math.MaxInt8)
    fmt.Println("最小int8:", math.MinInt8)
    fmt.Println("最大float64:", math.MaxFloat64)
    
    // 类型方法
    type MyType int
    
    func (m MyType) Double() MyType {
        return m * 2
    }
    
    var mt MyType = 5
    fmt.Println("Double:", mt.Double())
    
    // 匿名结构体
    anon := struct {
        Name string
        Age  int
    }{
        Name: "匿名",
        Age:  25,
    }
    fmt.Println(anon)
    
    // 嵌入类型
    type Address struct {
        City string
    }
    
    type Employee struct {
        Name    string
        Address // 嵌入
    }
    
    emp := Employee{
        Name: "张三",
        Address: Address{City: "北京"},
    }
    fmt.Println(emp.City)  // 通过嵌入访问
    
    // 标签(struct tags)
    type User struct {
        Name  string `json:"name" validate:"required"`
        Email string `json:"email" validate:"email"`
    }
    
    // 泛型(Go 1.18+)
    type Number interface {
        int | int64 | float64
    }
    
    func Sum[T Number](nums []T) T {
        var sum T
        for _, num := range nums {
            sum += num
        }
        return sum
    }
    
    result := Sum([]int{1, 2, 3, 4, 5})
    fmt.Println("Sum:", result)
}

JavaScript 数据类型

// 原始类型(Primitive Types)
// 字符串类型
let str1 = "双引号字符串";
let str2 = '单引号字符串';
let str3 = `模板字符串,可以包含变量 ${name}`;
let str4 = String(123);  // 类型转换
let str5 = new String("对象字符串");  // 不推荐

// 数值类型
let num1 = 123;           // 整数
let num2 = -456;          // 负数
let num3 = 3.14;          // 浮点数
let num4 = 1.23e4;        // 科学计数法 12300
let num5 = 0xFF;          // 十六进制 255
let num6 = 0o777;         // 八进制 511
let num7 = 0b1111;        // 二进制 15
let num8 = Infinity;      // 无穷大
let num9 = -Infinity;     // 负无穷大
let num10 = NaN;          // 非数字
let num11 = Number.MAX_VALUE;  // 最大数值
let num12 = Number.MIN_VALUE;  // 最小数值

// 大整数类型(ES2020+)
let bigInt1 = 123n;
let bigInt2 = BigInt(123);
let bigInt3 = BigInt("123456789012345678901234567890");

// 布尔类型
let bool1 = true;
let bool2 = false;
let bool3 = Boolean(1);       // true
let bool4 = Boolean(0);       // false
let bool5 = Boolean("hello"); // true
let bool6 = Boolean("");      // false
let bool7 = !!value;          // 双重否定转换

// Undefined类型
let undef1;
let undef2 = undefined;
let undef3 = void 0;          // 另一种写法

// Null类型
let null1 = null;

// Symbol类型(ES2015+)
let sym1 = Symbol("description");
let sym2 = Symbol("description");
console.log(sym1 === sym2);  // false,唯一性

// 全局Symbol注册表
let globalSym1 = Symbol.for("global");
let globalSym2 = Symbol.for("global");
console.log(globalSym1 === globalSym2);  // true

// Symbol作为对象属性键
let obj = {
    [Symbol("key")]: "value",
    [Symbol.iterator]: function*() {
        yield 1;
        yield 2;
    }
};

// 对象类型(Object Types)
// 普通对象
let obj1 = {key: "value"};
let obj2 = new Object();
let obj3 = Object.create(null);  // 无原型对象

// 数组
let arr1 = [1, 2, 3];
let arr2 = new Array(1, 2, 3);
let arr3 = Array.of(1, 2, 3);
let arr4 = Array.from("hello");  // ['h', 'e', 'l', 'l', 'o']

// 函数
function func1() {}
let func2 = function() {};
let func3 = () => {};
let func4 = new Function('a', 'b', 'return a + b');

// 日期对象
let date1 = new Date();
let date2 = new Date(2024, 0, 1);  // 2024年1月1日
let date3 = new Date("2024-01-01");

// 正则表达式
let regex1 = /pattern/;
let regex2 = new RegExp("pattern");
let regex3 = /pattern/gi;  // 全局、忽略大小写

// 错误对象
let error1 = new Error("错误信息");
let error2 = new TypeError("类型错误");
let error3 = new RangeError("范围错误");

// Map对象(ES2015+)
let map = new Map();
map.set("key", "value");
map.set(1, "number");
map.set(true, "boolean");

// Set对象(ES2015+)
let set = new Set();
set.add(1);
set.add(2);
set.add(2);  // 重复值不会添加
set.add("string");

// WeakMap对象(ES2015+)
let weakMap = new WeakMap();
let keyObj = {};
weakMap.set(keyObj, "value");

// WeakSet对象(ES2015+)
let weakSet = new WeakSet();
weakSet.add(keyObj);

// Promise对象(ES2015+)
let promise = new Promise((resolve, reject) => {
    resolve("成功");
});

// Proxy对象(ES2015+)
let target = {key: "value"};
let proxy = new Proxy(target, {
    get: function(obj, prop) {
        return prop in obj ? obj[prop] : "默认值";
    }
});

// Reflect对象(ES2015+)
let objReflect = {};
Reflect.set(objReflect, 'key', 'value');
console.log(Reflect.get(objReflect, 'key'));

// 类(ES2015+)
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    
    greet() {
        console.log(`Hello, ${this.name}`);
    }
}

// 静态方法和属性
class MyClass {
    static staticProp = "静态属性";
    
    static staticMethod() {
        return "静态方法";
    }
}

// 私有字段(ES2022+)
class PrivateClass {
    #privateField = "私有字段";
    
    getPrivate() {
        return this.#privateField;
    }
}

// 类型检查
let value = "hello";

console.log(typeof value);        // "string"
console.log(typeof 123);          // "number"
console.log(typeof true);         // "boolean"
console.log(typeof undefined);    // "undefined"
console.log(typeof null);         // "object" (历史遗留问题)
console.log(typeof {});           // "object"
console.log(typeof []);           // "object"
console.log(typeof function(){}); // "function"
console.log(typeof Symbol());     // "symbol"
console.log(typeof 123n);         // "bigint"

// instanceof 检查
console.log([] instanceof Array);        // true
console.log({} instanceof Object);       // true
console.log(function(){} instanceof Function); // true
console.log(new Date() instanceof Date); // true

// Array.isArray 检查
console.log(Array.isArray([]));  // true
console.log(Array.isArray({}));  // false

// Object.prototype.toString 检查
console.log(Object.prototype.toString.call([]));      // "[object Array]"
console.log(Object.prototype.toString.call({}));      // "[object Object]"
console.log(Object.prototype.toString.call(null));    // "[object Null]"
console.log(Object.prototype.toString.call(undefined)); // "[object Undefined]"

// 类型转换
// 字符串转换
let strNum = String(123);
let strBool = String(true);
let strObj = String({key: "value"});
let strNull = String(null);
let strUndef = String(undefined);

// 数字转换
let numStr = Number("123");
let numBool = Number(true);
let numObj = Number({valueOf: () => 42});
let numParseInt = parseInt("123");
let numParseFloat = parseFloat("3.14");

// 布尔转换
let boolStr = Boolean("hello");
let boolNum = Boolean(0);
let boolObj = Boolean({});
let boolArr = Boolean([]);

// 隐式类型转换
let result1 = "5" + 3;      // "53" (字符串拼接)
let result2 = "5" - 3;      // 2 (数字减法)
let result3 = "5" * 3;      // 15 (数字乘法)
let result4 = "5" / 2;      // 2.5 (数字除法)
let result5 = "5" % 2;      // 1 (数字取模)

// == 和 === 的区别
console.log(5 == "5");      // true (类型转换后比较)
console.log(5 === "5");     // false (类型和值都比较)
console.log(0 == false);    // true
console.log(0 === false);   // false
console.log(null == undefined);  // true
console.log(null === undefined); // false

// 类型转换规则
// ToPrimitive - 转换为原始值
let objToPrim = {
    valueOf: function() { return 42; },
    toString: function() { return "hello"; }
};
console.log(+objToPrim);  // 42 (优先调用valueOf)

// ToNumber - 转换为数字
console.log(Number("123"));    // 123
console.log(Number("3.14"));   // 3.14
console.log(Number(""));       // 0
console.log(Number("hello"));  // NaN
console.log(Number(true));     // 1
console.log(Number(false));    // 0
console.log(Number(null));     // 0
console.log(Number(undefined)); // NaN

// ToString - 转换为字符串
console.log(String(123));      // "123"
console.log(String(true));     // "true"
console.log(String(null));     // "null"
console.log(String(undefined)); // "undefined"
console.log(String({}));       // "[object Object]"

// ToBoolean - 转换为布尔值
// 以下值转换为false
console.log(Boolean(false));   // false
console.log(Boolean(0));       // false
console.log(Boolean(-0));      // false
console.log(Boolean(0n));      // false
console.log(Boolean(""));      // false
console.log(Boolean(null));    // false
console.log(Boolean(undefined)); // false
console.log(Boolean(NaN));     // false

// 其他所有值转换为true
console.log(Boolean("0"));     // true
console.log(Boolean("false")); // true
console.log(Boolean([]));      // true
console.log(Boolean({}));      // true
console.log(Boolean(function(){})); // true

// 类型安全函数
function safeAdd(a, b) {
    if (typeof a !== 'number' || typeof b !== 'number') {
        throw new TypeError('参数必须是数字');
    }
    return a + b;
}

// TypeScript类型注释(虽然不是原生支持)
/**
 * @param {number} a
 * @param {number} b
 * @returns {number}
 */
function add(a, b) {
    return a + b;
}

// JSDoc类型注释
/**
 * @typedef {Object} User
 * @property {string} name
 * @property {number} age
 * @property {string[]} hobbies
 */

/**
 * @param {User} user
 * @returns {string}
 */
function greetUser(user) {
    return `Hello, ${user.name}`;
}

// 类型守卫
function isString(value) {
    return typeof value === 'string';
}

function process(value) {
    if (isString(value)) {
        // TypeScript中这里value会被推断为string类型
        return value.toUpperCase();
    }
    return value;
}

以上是三种语言在变量和类型方面的详细对照,涵盖了基本语法、数据类型、类型转换、作用域等核心概念。每种语言都有其独特的特性和最佳实践。

昨天以前首页

语法全景对照

2026年3月27日 10:54

PHP、Go、JavaScript (ES6+) 核心语法全景对照指南

第一部分:变量声明与基础数据类型

三种语言在变量作用域、类型检查机制上有着本质区别:

  • PHP:弱类型(但 PHP 7/8 引入了强类型声明),变量以 $ 开头,作用域通常在函数内。
  • Go:静态强类型,编译型语言,严格区分类型,支持类型推导 :=,包级作用域与块级作用域。
  • JavaScript:弱类型,动态脚本语言,推荐使用 letconst 实现块级作用域。

1. PHP 实现

<?php
declare(strict_types=1); // 开启严格类型模式

// 1. 变量与常量声明
$username = "Alice"; // 字符串
$age = 25;           // 整型
$balance = 100.50;   // 浮点型
$isActive = true;    // 布尔型
$data = null;        // 空值

// 常量
define('MAX_LOGIN_ATTEMPTS', 5);
const APP_VERSION = "1.0.0";

// 2. 字符串操作
$greeting = "Hello, $username!"; // 双引号支持变量解析
$concat = 'Age: ' . $age;        // 单引号不支持解析,使用 . 拼接

// 3. 类型声明 (PHP 7.4+)
function printUserInfo(string $name, int $age, ?float $bal): void {
    echo "User: {$name}, Age: {$age}, Balance: " . ($bal ?? 0.0) . "\n";
}

printUserInfo($username, $age, $balance);

2. Go 实现

package main

import "fmt"

// 1. 包级变量与常量声明
const MaxLoginAttempts int = 5
const AppVersion = "1.0.0" // 无类型常量,根据上下文推导

var globalConfig string = "default"

func variablesDemo() {
    // 2. 局部变量声明
    var username string = "Alice"
    var age int = 25
    var balance float64 = 100.50
    var isActive bool = true
    
    // 短变量声明 (仅限函数内部)
    data := "Some Data" // 自动推导为 string
    
    // Go 中没有 null,只有各类型的零值 (nil 适用于指针、切片、映射、接口等)
    var ptr *int = nil 

    // 3. 字符串操作
    // Go 字符串不可变,支持双引号和反引号(多行)
    greeting := fmt.Sprintf("Hello, %s!", username)
    concat := "Age: " + fmt.Sprint(age)

    printUserInfo(username, age, balance)
    fmt.Println(greeting, concat, isActive, data, ptr)
}

// 4. 函数参数严格定型
func printUserInfo(name string, age int, bal float64) {
    fmt.Printf("User: %s, Age: %d, Balance: %.2f\n", name, age, bal)
}

3. JavaScript 实现

// 1. 变量与常量声明 (ES6+)
const MAX_LOGIN_ATTEMPTS = 5; // 常量,不可重新赋值
const APP_VERSION = "1.0.0";

let username = "Alice"; // 块级作用域变量
let age = 25;           // Number 类型 (JS 中不区分整型和浮点型)
let balance = 100.50;   // Number 类型
let isActive = true;    // Boolean
let data = null;        // Null 类型
let notDefined;         // Undefined 类型

// 2. 字符串操作
// 模板字符串 (Template Literals),支持多行和表达式插值
let greeting = `Hello, ${username}!`; 
let concat = 'Age: ' + age;

// 3. 弱类型函数 (可以使用 TypeScript 增加强类型)
function printUserInfo(name, age, bal) {
    // 使用 nullish coalescing operator (??) 赋默认值
    console.log(`User: ${name}, Age: ${age}, Balance: ${bal ?? 0.0}`);
}

printUserInfo(username, age, balance);

第二部分:复合数据结构(数组、字典、切片)

  • PHP:天下无敌的 Array(实际上是有序哈希表),既当列表又当字典。
  • Go:严格区分 Array(定长)、Slice(动态切片)和 Map(哈希表)。
  • JavaScript:区分 Array(动态列表)和 Object/Map(键值对)。

1. PHP 的万能数组

<?php
// 1. 索引数组 (List)
$fruits = ["Apple", "Banana", "Orange"];
$fruits[] = "Mango"; // 追加元素
array_push($fruits, "Grape");

// 2. 关联数组 (Map/Dictionary)
$user = [
    "id" => 101,
    "username" => "bob_smith",
    "email" => "bob@example.com",
    "roles" => ["admin", "editor"] // 嵌套数组
];

// 添加/修改键值对
$user["status"] = "active";

// 3. 数组遍历
foreach ($user as $key => $value) {
    if (is_array($value)) {
        echo "$key: " . implode(", ", $value) . "\n";
    } else {
        echo "$key: $value\n";
    }
}

// 4. 常用数组操作
$keys = array_keys($user);
$hasEmail = array_key_exists("email", $user);
$filtered = array_filter($fruits, fn($f) => strlen($f) > 5); // 闭包过滤

2. Go 的 Slice 与 Map

package main

import (
    "fmt"
    "strings"
)

func dataStructuresDemo() {
    // 1. 数组 (Array) - 长度固定,较少直接使用
    var arr [3]string = [3]string{"Apple", "Banana", "Orange"}

    // 2. 切片 (Slice) - 动态数组,最常用
    fruits := []string{"Apple", "Banana", "Orange"}
    fruits = append(fruits, "Mango", "Grape") // 追加元素

    // 3. 映射 (Map) - 键值对,必须使用 make 初始化或字面量初始化
    user := map[string]interface{}{ // 使用 interface{} 支持不同类型的值
        "id":       101,
        "username": "bob_smith",
        "email":    "bob@example.com",
        "roles":    []string{"admin", "editor"},
    }

    // 添加/修改键值对
    user["status"] = "active"

    // 4. 遍历
    for key, value := range user {
        // 类型断言 (Type Assertion)
        if roles, ok := value.([]string); ok {
            fmt.Printf("%s: %s\n", key, strings.Join(roles, ", "))
        } else {
            fmt.Printf("%s: %v\n", key, value)
        }
    }

    // 5. 检查键是否存在
    email, exists := user["email"]
    if exists {
        fmt.Println("Email found:", email)
    }
}

3. JavaScript 的 Array 与 Object

// 1. 数组 (Array)
const fruits = ["Apple", "Banana", "Orange"];
fruits.push("Mango", "Grape"); // 追加元素

// 2. 对象 (Object) - 作为字典使用
const user = {
    id: 101,
    username: "bob_smith",
    email: "bob@example.com",
    roles: ["admin", "editor"]
};

// 添加/修改键值对
user.status = "active";
user["last_login"] = "2023-10-01";

// 3. 遍历对象
for (const [key, value] of Object.entries(user)) {
    if (Array.isArray(value)) {
        console.log(`${key}: ${value.join(", ")}`);
    } else {
        console.log(`${key}: ${value}`);
    }
}

// 4. 常用高级操作 (ES6 数组方法)
const keys = Object.keys(user);
const hasEmail = "email" in user;
// 链式调用
const longFruits = fruits
    .filter(f => f.length > 5)
    .map(f => f.toUpperCase());

第三部分:函数、闭包与高阶特性

1. PHP 函数特性

<?php
// 1. 默认参数与可变参数
function buildQuery(string $table, array $conditions = [], string ...$fields): string {
    $select = empty($fields) ? "*" : implode(", ", $fields);
    $sql = "SELECT {$select} FROM {$table}";
    if (!empty($conditions)) {
        $sql .= " WHERE " . http_build_query($conditions, '', ' AND ');
    }
    return $sql;
}

// 2. 匿名函数与闭包 (使用 use 关键字引入外部变量)
$multiplier = 3;
$calculate = function (int $number) use ($multiplier): int {
    return $number * $multiplier;
};

// 3. 箭头函数 (PHP 7.4+,单行,自动捕获外部变量)
$calculateArrow = fn(int $number) => $number * $multiplier;

// 4. 命名参数 (PHP 8.0+)
$query = buildQuery(
    fields: "id", "name",
    table: "users",
    conditions: ["status" => 1]
);

2. Go 函数特性

package main

import (
    "fmt"
    "strings"
)

// 1. 多返回值与可变参数
func buildQuery(table string, conditions map[string]interface{}, fields ...string) (string, error) {
    if table == "" {
        return "", fmt.Errorf("table name cannot be empty")
    }
    
    selectFields := "*"
    if len(fields) > 0 {
        selectFields = strings.Join(fields, ", ")
    }
    
    sql := fmt.Sprintf("SELECT %s FROM %s", selectFields, table)
    // 省略复杂的 conditions 拼接逻辑...
    
    return sql, nil
}

func functionDemo() {
    // 2. 匿名函数与闭包 (自动捕获外部变量,无需类似 PHP 的 use)
    multiplier := 3
    calculate := func(number int) int {
        return number * multiplier
    }
    
    fmt.Println(calculate(10)) // 30

    // 3. 延迟执行 defer (Go 独有,常用于资源清理)
    defer fmt.Println("This runs at the end of functionDemo")
    
    // 4. 处理多返回值
    query, err := buildQuery("users", nil, "id", "name")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println(query)
}

3. JavaScript 函数特性

// 1. 默认参数与剩余参数 (Rest parameters)
function buildQuery(table, conditions = {}, ...fields) {
    const selectFields = fields.length === 0 ? "*" : fields.join(", ");
    let sql = `SELECT ${selectFields} FROM ${table}`;
    
    const condKeys = Object.keys(conditions);
    if (condKeys.length > 0) {
        const where = condKeys.map(k => `${k}=${conditions[k]}`).join(" AND ");
        sql += ` WHERE ${where}`;
    }
    return sql;
}

// 2. 匿名函数赋值
const calculate = function(number) {
    return number * multiplier; // 依赖外部作用域变量
};

// 3. 箭头函数 (Arrow Functions, 不绑定自己的 this)
let multiplier = 3;
const calculateArrow = (number) => number * multiplier;

// 4. 解构赋值传参
function processUser({ id, username, roles = [] }) {
    console.log(`Processing ${username} (ID: ${id}) with roles: ${roles}`);
}

const userObj = { id: 1, username: "admin", email: "a@a.com" };
processUser(userObj); // 只提取需要的字段

第四部分:面向对象 (OOP) 与结构体

  • PHP:经典的基于类的单继承 OOP(Class, Interface, Abstract, Trait)。
  • Go:没有 Class 和继承。通过 Struct(结构体)封装数据,通过给结构体绑定方法实现行为,通过 Interface(鸭子类型)实现多态,通过结构体嵌套实现组合。
  • JavaScript:基于原型链(Prototype)。ES6 引入了 class 语法糖。

1. PHP 的经典 OOP

<?php

// 接口定义契约
interface LoggerInterface {
    public function log(string $message): void;
}

// Trait 代码复用机制
trait TimestampTrait {
    protected function getTimestamp(): string {
        return date('Y-m-d H:i:s');
    }
}

// 抽象类
abstract class BaseService {
    protected LoggerInterface $logger;
    
    public function __construct(LoggerInterface $logger) {
        $this->logger = $logger;
    }
    
    abstract public function execute(): bool;
}

// 具体实现类
class PaymentService extends BaseService {
    use TimestampTrait;

    // PHP 8.0 构造器属性提升
    public function __construct(
        LoggerInterface $logger,
        private float $amount
    ) {
        parent::__construct($logger);
    }

    public function execute(): bool {
        $time = $this->getTimestamp();
        $this->logger->log("[{$time}] Processing payment of {$this->amount}");
        return true;
    }
}

// 匿名类实现接口
$consoleLogger = new class implements LoggerInterface {
    public function log(string $message): void {
        echo "CONSOLE: $message\n";
    }
};

$service = new PaymentService($consoleLogger, 99.99);
$service->execute();

2. Go 的结构体与接口 (组合与鸭子类型)

package main

import (
    "fmt"
    "time"
)

// 1. 接口定义 (Go 的接口是隐式实现的)
type Logger interface {
    Log(message string)
}

// 2. 结构体 (代替类)
type ConsoleLogger struct {
    Prefix string
}

// 3. 为结构体绑定方法 (实现 Logger 接口)
// 只要实现了 Log 方法,它就是 Logger
func (c *ConsoleLogger) Log(message string) {
    fmt.Printf("%s: %s\n", c.Prefix, message)
}

// 4. 基础服务结构体
type BaseService struct {
    logger Logger // 依赖注入
}

// 5. 具体服务结构体 (通过嵌套实现类似继承的"组合")
type PaymentService struct {
    BaseService // 匿名嵌套,继承了 BaseService 的字段
    Amount      float64
}

// 为 PaymentService 定义方法
func (p *PaymentService) Execute() bool {
    timestamp := time.Now().Format("2006-01-02 15:04:05")
    msg := fmt.Sprintf("[%s] Processing payment of %.2f", timestamp, p.Amount)
    // 调用嵌套结构体中的 logger
    p.logger.Log(msg)
    return true
}

func oopDemo() {
    logger := &ConsoleLogger{Prefix: "SYS_LOG"}
    
    service := &PaymentService{
        BaseService: BaseService{logger: logger},
        Amount:      99.99,
    }
    
    service.Execute()
}

3. JavaScript 的 Class 语法糖

// JS 没有内置的 Interface,通常靠文档或 TypeScript 约束

// 1. 定义类
class BaseService {
    // 私有字段 (ES2022+)
    #logger;

    constructor(logger) {
        this.#logger = logger;
    }

    // Getter
    get logger() {
        return this.#logger;
    }

    // 抛出错误模拟抽象方法
    execute() {
        throw new Error("Method 'execute()' must be implemented.");
    }
}

// 2. 继承
class PaymentService extends BaseService {
    #amount;

    constructor(logger, amount) {
        super(logger); // 必须调用 super
        this.#amount = amount;
    }

    // 私有方法
    #getTimestamp() {
        return new Date().toISOString();
    }

    // 方法重写
    execute() {
        const time = this.#getTimestamp();
        this.logger.log(`[${time}] Processing payment of ${this.#amount}`);
        return true;
    }
}

// 3. 对象字面量实现依赖 (鸭子类型)
const consoleLogger = {
    log: function(message) {
        console.log(`CONSOLE: ${message}`);
    }
};

const service = new PaymentService(consoleLogger, 99.99);
service.execute();

第五部分:错误与异常处理

1. PHP (Try-Catch)

<?php
class CustomDatabaseException extends Exception {}

function connectDB(string $host) {
    if (empty($host)) {
        // 抛出异常
        throw new CustomDatabaseException("Host cannot be empty");
    }
    // 模拟连接成功
    return true;
}

try {
    connectDB("");
} catch (CustomDatabaseException $e) {
    error_log("DB Error: " . $e->getMessage());
} catch (Exception $e) {
    // 捕获其他所有异常
    error_log("General Error: " . $e->getMessage());
} finally {
    // 无论是否报错都会执行,常用于释放资源
    echo "Cleanup resources.\n";
}

2. Go (Error 值返回与 Panic)

Go 不推荐使用类似 try-catch 的控制流,而是将错误作为普通的返回值处理。

package main

import (
    "errors"
    "fmt"
)

// 定义自定义错误变量
var ErrEmptyHost = errors.New("host cannot be empty")

func connectDB(host string) (bool, error) {
    if host == "" {
        // 返回错误值
        return false, ErrEmptyHost
    }
    return true, nil
}

func errorDemo() {
    success, err := connectDB("")
    
    // 显式检查错误 (Go 的标志性写法)
    if err != nil {
        // 错误判定 (Go 1.13+)
        if errors.Is(err, ErrEmptyHost) {
            fmt.Println("DB Error: Provided host is empty.")
        } else {
            fmt.Println("Unknown Error:", err)
        }
        return
    }
    
    fmt.Println("Connected:", success)
    
    // Go 中的 Panic/Recover 仅用于极其严重的不可恢复错误
    // 类似于 try-catch,但不应作为常规业务逻辑
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from panic:", r)
        }
    }()
    // panic("Critical failure!") 
}

3. JavaScript (Try-Catch)

class CustomDatabaseError extends Error {
    constructor(message) {
        super(message);
        this.name = "CustomDatabaseError";
    }
}

function connectDB(host) {
    if (!host) {
        throw new CustomDatabaseError("Host cannot be empty");
    }
    return true;
}

try {
    connectDB("");
} catch (error) {
    if (error instanceof CustomDatabaseError) {
        console.error("DB Error:", error.message);
    } else {
        console.error("General Error:", error);
    }
} finally {
    console.log("Cleanup resources.");
}

第六部分:并发与异步处理 (核心差异)

这是三种语言差异最大的地方:

  • PHP:传统模型是同步阻塞的(多进程模型,如 PHP-FPM),每次请求一个进程。
  • Go:天生为并发设计。使用轻量级的 goroutinechannel 进行通信。
  • JavaScript:单线程事件循环。使用回调、Promiseasync/await 处理非阻塞 I/O。

1. PHP (同步阻塞)

<?php
// PHP 原生核心不支持非阻塞异步(不借助 Swoole/ReactPHP 等扩展)
function fetchData(string $url): string {
    sleep(2); // 模拟耗时网络请求,这里会阻塞整个进程
    return "Data from $url";
}

echo "Start\n";
$data1 = fetchData("API_1"); // 阻塞 2 秒
$data2 = fetchData("API_2"); // 阻塞 2 秒
echo "End: $data1, $data2\n"; // 总耗时 4 秒

2. Go (Goroutines 与 Channels)

Go 语言可以通过 go 关键字瞬间启动成千上万个并发任务。

package main

import (
    "fmt"
    "sync"
    "time"
)

// 模拟耗时请求
func fetchData(url string, ch chan<- string, wg *sync.WaitGroup) {
    defer wg.Done() // 函数结束时通知 WaitGroup 完成
    
    time.Sleep(2 * time.Second) // 模拟耗时
    // 将结果发送到通道 Channel
    ch <- fmt.Sprintf("Data from %s", url) 
}

func concurrencyDemo() {
    fmt.Println("Start")
    
    // 创建一个通道用于接收结果
    results := make(chan string, 2)
    // WaitGroup 用于等待所有 goroutine 完成
    var wg sync.WaitGroup
    
    urls := []string{"API_1", "API_2"}
    
    for _, url := range urls {
        wg.Add(1)
        // 开启 Goroutine 并发执行
        go fetchData(url, results, &wg) 
    }
    
    // 开启一个后台 Goroutine 等待所有任务完成并关闭通道
    go func() {
        wg.Wait()
        close(results)
    }()
    
    // 从通道中读取数据(阻塞直到有数据或通道关闭)
    for data := range results {
        fmt.Println("Received:", data)
    }
    
    fmt.Println("End") // 总耗时约 2 秒
}

3. JavaScript (Async / Await 与 Promise)

JS 使用异步非阻塞 I/O,主线程不等待,而是把回调挂起。

// 模拟返回 Promise 的耗时请求
function fetchData(url) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(`Data from ${url}`);
        }, 2000);
    });
}

// 使用 async/await 以同步的代码风格写异步逻辑
async function main() {
    console.log("Start");
    
    try {
        // 并发执行多个 Promise
        const [data1, data2] = await Promise.all([
            fetchData("API_1"),
            fetchData("API_2")
        ]);
        
        console.log(`Received: ${data1}`);
        console.log(`Received: ${data2}`);
    } catch (error) {
        console.error("Async Error:", error);
    }
    
    console.log("End"); // 总耗时约 2 秒
}

main();

总结

  • PHP:围绕 Web 请求生命周期构建,数组操作极其灵活,OOP 体系严谨成熟,适合快速开发传统 Web 后端。
  • Go:静态编译,极简语法,舍弃了传统类继承,以强悍的并发能力(Goroutine/Channel)和极高的运行效率见长,适合微服务和云原生架构。
  • JavaScript:一处编写到处运行,对象和函数高度灵活,以事件循环和异步非阻塞为核心,全栈(Node.js + 前端)开发的霸主。

RSA攻略

2026年3月27日 10:02

成为 推荐、搜索、广告 (RSA) 领域的算法工程师,是目前工业界算法需求最旺盛、变现最直接的方向。这三个领域虽然业务场景不同,但底层技术架构高度一致,统称为 “信息流与检索” 技术。

以下是进阶之路,分为四个阶段:


第一阶段:夯实基础 (地基期)

这是进入算法领域的敲门砖,无论哪个方向都绕不开。

  • 数学功底
    • 统计学:理解概率分布、假设检验、极大似然估计(推荐系统本质是在预测概率)。
    • 最优化:梯度下降 (SGD)、正则化 (L1/L2)、损失函数(Loss Function)。
  • 编程能力
    • Python:精通 NumPy, Pandas, Scikit-learn。
    • SQL极其重要。RSA 工程师 50% 的时间在处理数据,必须能熟练编写复杂的 Hive/Spark SQL。
    • 数据结构与算法:LeetCode 必刷,重点关注:哈希表、二分查找、动态规划、图算法。
  • 机器学习基础
    • 掌握逻辑回归 (LR)、支持向量机 (SVM)、决策树。
    • 重点掌握集成学习:XGBoost, LightGBM, CatBoost(工业界处理表格类数据的利器)。

第二阶段:掌握 RSA 核心架构 (入门期)

工业界的推荐/搜索/广告系统通常是一个**“漏斗形”**架构。你需要学习每一层的核心逻辑。

  • 核心流程:召回 (Recall) → 粗排 → 精排 (Ranking) → 重排 (Re-ranking)
  • 召回层 (Retrieval)
    • 协同过滤 (CF):User-based, Item-based。
    • 向量化召回 (Embedding):Word2Vec, Item2Vec, DeepWalk。
    • 多路召回策略:热度、标签、兴趣、地理位置等多维度聚合。
  • 排序层 (Ranking)
    • 特征工程:这是 RSA 的灵魂。学习如何处理类别特征(One-hot)、数值特征(归一化)、交叉特征。
    • 经典模型:FM (Factorization Machines), DeepFM, Wide & Deep。
  • 评估指标
    • 理解 CTR (点击率)、CVR (转化率)。
    • 学习离线评估指标:AUC, GAUC, NDCG, MAP

第三阶段:工业级工程与大数据 (实战期)

算法工程师不只是写模型,RSA 领域对“大数据”和“在线工程”的要求极高。

  • 大数据处理
    • 学习 SparkFlink:掌握分布式处理千万级、亿级数据的能力。
  • 特征工程进阶
    • 学习如何处理大规模稀疏特征
    • 掌握特征存取工具:Redis, Cassandra 或特征平台。
  • A/B Testing
    • 学习如何科学地设计实验,理解显著性检验。这是评价算法上线效果的唯一标准。
  • 深度学习模型进阶
    • 序列建模:DIN, DIEN (捕捉用户兴趣随时间的变化)。
    • 多任务学习 (MTL):MMoE, ESSM (同时预测点击和转化)。

第四阶段:前沿探索与进阶 (专家期)

当你在工业界有了 2-3 年经验后,需要关注更深层次的问题。

  • 图神经网络 (GNN):利用用户-商品的二分图进行建模(如 GraphSage, PinSage)。
  • 强化学习 (RL):解决推荐系统的长期收益问题(如用户留存)。
  • LLM + RSA:研究如何利用大模型(如 GPT、Llama)生成的语义 Embedding 来增强推荐效果,或利用大模型进行冷启动推荐。
  • 系统架构设计:考虑如何支撑每秒万级 (QPS) 的高并发请求,如何平衡模型的复杂性推理延迟

如何高效进阶?

  1. 打好 SQL 基础:很多新人死在不会写复杂的 SQL 取特征上。
  2. 阅读经典论文
    • 必读 Google 的 Wide & Deep
    • 必读阿里、美团、字节跳动发布的技术博客(它们代表了国内 RSA 的最高水平)。
  3. 参加竞赛 (Kaggle/天池)
    • 找一个“点击率预测 (CTR Prediction)”或“个性化推荐”的比赛,走完从数据清洗到特征工程再到模型融合的全流程。
  4. 关注业务逻辑
    • 算法是为业务服务的。理解为什么搜索需要相关性,为什么广告需要考虑出价 (eCPM),为什么推荐需要考虑多样性和惊喜感。

一句话总结: RSA 工程师是 “数据科学家 + 软件工程师 + 业务专家” 的结合体。先从写好 SQL 和掌握逻辑回归开始,再逐步攻克深度学习和分布式架构。

算法工程师分类

2026年3月27日 10:01

算法工程师是一个非常广阔的领域,随着人工智能和大数据的发展,岗位划分也越来越精细。一般来说,算法工程师主要分为以下几个核心方向:

1. 计算机视觉 (CV - Computer Vision)

这是目前应用最广泛的方向之一,主要让计算机“看懂”图像和视频。

  • 常见应用:人脸识别、自动驾驶(目标检测)、医疗影像分析、OCR(文字识别)、视频监控安防。
  • 核心技能
    • 基础理论:图像处理基础、矩阵运算、卷积神经网络 (CNN)。
    • 经典模型:ResNet, YOLO, Faster R-CNN, Vision Transformer (ViT)。
    • 工具框架:OpenCV, PyTorch, TensorFlow。

2. 自然语言处理 (NLP - Natural Language Processing)

专注于让计算机“听懂”或“读懂”人类语言,当前最火的大模型 (LLM) 就属于这个范畴。

  • 常见应用:机器翻译、情感分析、智能客服、文本摘要、ChatGPT 等大语言模型。
  • 核心技能
    • 基础理论:词向量 (Word2Vec)、循环神经网络 (RNN/LSTM)、Attention 机制。
    • 前沿模型:Transformer, BERT, GPT 系列、LLaMA 等。
    • 领域知识:文本清洗、分词、语义表示、提示工程 (Prompt Engineering)。

3. 推荐 / 搜索 / 广告 (RSA - Recommendation/Search/Advertising)

这通常被称为“工业界最赚钱”的算法方向,主要解决信息过载问题。

  • 常见应用:抖音/小红书的个性化推荐、淘宝的商品搜索、百度/腾讯的广告精准投放。
  • 核心技能
    • 经典算法:协同过滤、FM (Factorization Machines)、DeepFM、GBDT+LR。
    • 工程能力特征工程(非常重要)、召回与排序架构、冷启动策略。
    • 大数据工具:Spark, Flink, Hive (SQL 是基本功)。

4. 语音处理 (Speech/Audio)

处理语音信号,实现人机交互。

  • 常见应用:语音识别 (ASR)、语音合成 (TTS)、声纹识别、降噪处理。
  • 核心技能
    • 基础理论:信号处理(傅里叶变换)、声学模型、语言模型。
    • 模型:WaveNet, Conformer, Whisper 等。

5. 机器学习 / 数据挖掘 (General ML/DM)

更偏向于通用数据分析和预测。

  • 常见应用:金融风控(欺诈检测)、销量预测、用户画像建模、工业异常检测。
  • 核心技能
    • 统计学:概率分布、假设检验、回归分析。
    • 传统算法:逻辑回归、支持向量机 (SVM)、随机森林、XGBoost/LightGBM。

通用必备技能 (所有算法岗都需要)

无论你选择哪个方向,以下技能是算法工程师的“护城河”:

1. 数学基础

  • 线性代数(矩阵运算是深度学习的基石)。
  • 概率论与数理统计(模型评估、优化算法的基础)。
  • 最优化方法(梯度下降、正则化等)。

2. 编程能力

  • Python:算法开发的主力语言,需精通 NumPy, Pandas, Scikit-learn。
  • C++:在高性能计算、底层优化、自动驾驶等对延迟敏感的场景下必不可少。
  • 数据结构与算法:这是面试必考项,也是写出高效代码的前提。

3. 深度学习框架

  • 至少精通 PyTorchTensorFlow 其中之一。

4. 工程与落地能力

  • 算法不只是在实验室跑代码,还需要考虑模型部署(TensorRT, ONNX)、线上性能数据清洗等实际问题。

总结建议: 如果你是初学者,建议先打好 数学Python/数据结构 的基础,然后根据个人兴趣选择一个垂直领域(如 NLP 或 CV)深挖。如果你想追求更高的商业价值和就业机会,推荐算法大模型 (LLM) 是目前市场需求最旺盛的方向。

❌
❌