第四天:PHP 开发者快速掌握 Go 函数

yvsm5个月前Go语言6320

作为PHP开发者,你早已熟悉function定义函数、参数传值/传引用、return返回结果的逻辑。Go的函数体系更严谨、功能更丰富——支持多返回值、命名返回值、可变参数,且函数本身可作为参数/返回值(一等公民)。今天我们就以PHP函数为参照,快速掌握Go函数的核心语法和差异化特性。

一、Go函数基础(对标PHP函数声明)

Go函数通过func关键字声明,语法结构与PHP函数类似,但有“强类型约束”“无函数重载”等差异,先看核心对比:

1. 基本声明语法

特性Go函数PHP函数
声明关键字funcfunction
参数格式参数名+类型(如name string),类型后置参数名(可选类型提示),类型前置(如string $name
返回值支持单/多返回值,需声明类型仅单返回值,无需声明类型
函数重载不支持(同名函数报错)支持(通过参数个数/类型区分)

基础示例:Go函数 vs PHP函数

// Go函数声明(计算两数之和)
func add(a int, b int) int {
    return a + b
}

// 调用函数(需在main中执行,Go无全局执行)
func main() {
    res := add(10, 20)
    fmt.Println(res) // 输出30
}

PHP对应写法:

// PHP函数声明
function add(int $a, int $b) {
    return $a + $b;
}

// 全局调用
$res = add(10, 20);
echo $res; // 输出30

⚠️ 关键差异:
       1. Go函数的参数/返回值必须声明类型,PHP仅为“类型提示”(非强制);
       2. Go函数必须在包内声明,且只有main包的main函数是入口,无法全局调用;PHP函数可全局声明/调用。

2. 简化参数声明(同类型参数)

Go支持多个同类型参数合并声明类型,简化代码,PHP无此语法:

// Go:a和b均为int类型,只需写一次int
func add(a, b int) int {
    return a + b
}

PHP需逐个声明类型(或不声明):

// PHP:需逐个写int(或省略)
function add(int $a, int $b) {
    return $a + $b;
}

二、Go函数参数(对标PHP参数传递)

Go的参数传递只有“值传递”(无PHP的“传引用”),但可通过指针实现类似效果;同时支持“可变参数”,对标PHP的...$args

1. 普通参数(值传递)

Go默认按值传递参数(复制参数值),函数内修改不会影响外部变量,对标PHP的默认传值:

// Go值传递
func modifyNum(num int) {
    num = 100 // 修改的是副本,外部变量不变
}

func main() {
    n := 10
    modifyNum(n)
    fmt.Println(n) // 输出10(无变化)
}

PHP对应写法:

// PHP默认值传递
function modifyNum($num) {
    $num = 100;
}

$n = 10;
modifyNum($n);
echo $n; // 输出10(无变化)

2. 指针参数(对标PHP传引用)

Go无&$num传引用语法,但可通过“指针”传递变量内存地址,实现修改外部变量的效果:

// Go指针参数(对标PHP传引用)
func modifyNum(num *int) {
    *num = 100 // 解引用,修改原变量的值
}

func main() {
    n := 10
    modifyNum(&n) // 传递变量地址
    fmt.Println(n) // 输出100(已修改)
}

PHP传引用写法:

// PHP传引用
function modifyNum(&$num) {
    $num = 100;
}

$n = 10;
modifyNum($n);
echo $n; // 输出100(已修改)

3. 可变参数(对标PHP ...$args)

Go支持可变参数(需放在参数列表最后),用...类型声明,对标PHP的...$args

// Go可变参数(计算多个数的和)
func sum(nums ...int) int {
    total := 0
    // 遍历可变参数(本质是切片)
    for _, num := range nums {
        total += num
    }
    return total
}

func main() {
    res1 := sum(1, 2, 3)    // 传多个参数
    res2 := sum(10, 20, 30) // 传任意个数
    fmt.Println(res1, res2) // 输出6 60
}

PHP可变参数写法:

// PHP可变参数
function sum(...$nums) {
    $total = 0;
    foreach ($nums as $num) {
        $total += $num;
    }
    return $total;
}

$res1 = sum(1, 2, 3);
$res2 = sum(10, 20, 30);
echo $res1 . ' ' . $res2; // 输出6 60

三、Go函数返回值(PHP无的核心特性)

PHP函数仅支持单返回值(需返回多个值时要封装为数组/对象),而Go原生支持“多返回值”“命名返回值”,是核心优势之一。

1. 多返回值(对标PHP返回数组)

Go可声明多个返回值类型,函数内return多个值,对标PHP返回数组的场景:

// Go多返回值(获取用户信息:姓名+年龄)
func getUserInfo() (string, int) {
    return "张三", 30 // 返回两个值:字符串+整型
}

func main() {
    // 接收多个返回值
    name, age := getUserInfo()
    fmt.Printf("姓名:%s,年龄:%d\n", name, age)
    // 忽略某个返回值(用_占位)
    _, age2 := getUserInfo()
    fmt.Println("年龄:", age2)
}

PHP对应写法(返回数组):

// PHP返回数组模拟多返回值
function getUserInfo() {
    return ["张三", 30];
}

// 接收返回值
list($name, $age) = getUserInfo();
echo "姓名:{$name},年龄:{$age}\n";
// 忽略某个值
[, $age2] = getUserInfo();
echo "年龄:{$age2}";
}

2. 命名返回值(Go独有)

Go可给返回值命名,函数内无需显式return值(仅写return即可),简化代码:

// Go命名返回值
func calculate(a, b int) (sum int, sub int) {
    sum = a + b  // 直接赋值给命名返回值
    sub = a - b  // 直接赋值给命名返回值
    return       // 无需写return sum, sub
}

func main() {
    s, sb := calculate(10, 5)
    fmt.Println(s, sb) // 输出15 5
}

💡 适用场景:返回值较多时,命名返回值可提升代码可读性(明确每个返回值的含义)。

四、Go特殊函数类型(对标PHP匿名函数/闭包)

Go的函数是“一等公民”(可作为参数、返回值、赋值给变量),支持匿名函数、闭包,对标PHP的匿名函数/闭包,但语法更简洁。

1. 匿名函数(对标PHP匿名函数)

Go匿名函数无需命名,可直接赋值给变量或立即执行,对标PHP的function() {}

// Go匿名函数
func main() {
    // 赋值给变量
    sayHello := func(name string) {
        fmt.Printf("你好,%s\n", name)
    }
    sayHello("PHP开发者") // 调用

    // 立即执行匿名函数
    func(num int) {
        fmt.Println("立即执行:", num)
    }(100)
}

PHP对应写法:

// PHP匿名函数
// 赋值给变量
$sayHello = function($name) {
    echo "你好,{$name}\n";
};
$sayHello("PHP开发者");

// 立即执行匿名函数
(function($num) {
    echo "立即执行:{$num}\n";
})(100);

2. 闭包(对标PHP闭包)

Go闭包可捕获外部变量,对标PHP的use关键字,且无需显式声明(直接使用外部变量):

// Go闭包(捕获外部变量count)
func main() {
    count := 0
    // 闭包函数,捕获外部变量count
    increment := func() int {
        count++
        return count
    }

    fmt.Println(increment()) // 输出1
    fmt.Println(increment()) // 输出2
    fmt.Println(count)       // 输出2(外部变量已修改)
}

PHP对应写法(需用use):

// PHP闭包(需use捕获外部变量)
$count = 0;
$increment = function() use (&$count) { // 传引用才能修改外部变量
    $count++;
    return $count;
};

echo $increment() . "\n"; // 输出1
echo $increment() . "\n"; // 输出2
echo $count . "\n";       // 输出2

五、实战案例:PHP vs Go 函数综合使用

需求:定义函数,接收一个整数切片/数组,返回“总和”和“平均值”

Go写法(多返回值+可变参数)

package main

import "fmt"

// 接收可变参数,返回总和+平均值
func calcTotalAndAvg(nums ...int) (total int, avg float64) {
    total = 0
    for _, num := range nums {
        total += num
    }
    // 计算平均值(需类型转换)
    avg = float64(total) / float64(len(nums))
    return
}

func main() {
    t, a := calcTotalAndAvg(80, 90, 75, 85)
    fmt.Printf("总和:%d,平均值:%.2f\n", t, a) // 输出总和:330,平均值:82.50
}

PHP写法(返回数组模拟多返回值)

// 接收可变参数,返回总和+平均值
function calcTotalAndAvg(...$nums) {
    $total = 0;
    foreach ($nums as $num) {
        $total += $num;
    }
    $avg = $total / count($nums);
    return [$total, $avg];
}

list($t, $a) = calcTotalAndAvg(80, 90, 75, 85);
echo "总和:{$t},平均值:".number_format($a, 2)."\n"; // 输出总和:330,平均值:82.50

五、今日小结

今天我们以PHP函数为参照,掌握了Go函数的核心特性:

  1. Go函数用func声明,参数/返回值必须指定类型,无函数重载;

  2. Go参数传递只有值传递,可通过指针实现类似PHP传引用的效果;

  3. Go原生支持多返回值、命名返回值,无需像PHP那样封装数组;

  4. Go函数是一等公民,匿名函数/闭包语法简洁,捕获外部变量无需显式声明。

明天我们将学习Go的数组、切片与Map(对标PHP的索引数组/关联数组),详解Go复合数据类型的使用场景和核心差异,继续用PHP思维快速上手。

标签: PHP转Go

相关文章

第七天:PHP开发者快速掌握Go错误处理与文件操作 | 从PHP异常/文件函数到Go实战

作为PHP开发者,你熟悉用try/catch处理异常、file_get_contents/file_put_contents读写文件、mkdir创建目录。Go没有“异常(Exception)”的概念,...

第一天:从PHP到Golang,零基础入门的环境搭建与第一个程序

作为一名PHP开发者,当你决定接触Golang(简称Go)时,首先会好奇它和熟悉的PHP有哪些差异,以及如何快速迈出第一步。今天我们就从环境搭建和第一个Go程序入手,用PHP开发者熟悉的思维来解锁Go...

第五天:PHP开发者快速掌握Go数组、切片与Map | 从PHP数组到Go复合类型的转换

作为PHP开发者,你早已习惯了“万能数组”——既可以当索引数组用,也可以当关联数组用,长度动态变化、元素类型不限。而Go没有“万能数组”,而是将复合数据类型拆分为数组(array)、切...

第三天:PHP 开发者快速掌握 Go 运算符与流程控制

作为PHP开发者,你早已熟悉if/else、for、foreach等流程控制语法,以及+/-/*/、==/===等运算符。Go的运算符和流程控制语法与PHP高度相似,但也有不少“细节差异”——比如Go...

第八天:PHP开发者快速掌握Go并发编程 | Goroutine与Channel从入门到实战

作为PHP开发者,你知道实现并发需要依赖pcntl扩展创建多进程、pthreads扩展实现多线程,或借助Swoole/Workerman框架——步骤繁琐且资源消耗高。而Go内置原生并发支持:Gorou...

第二天:PHP 开发者快速掌握 Go 变量与数据类型

作为PHP开发者,你早已习惯了“无需声明类型、变量随用随定义”的弱类型特性,而Go作为强类型语言,变量必须显式声明类型(或通过推导确定)。今天我们就以PHP的变量/数据类型为参照,快速掌握Go的变量声...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。