PHP转Go速学手册

链接???? http://tigerb.cn/php2go/

前言

整理了一份简要的手册,帮助大家高效的上手Go语言,主要是通过对比PHP和Go的不同点来强化理解,内容主要分为以下四部分:

  • 语言层面差异

  • 基础语法差异

  • 避坑指南

  • 进阶使用

语言层面差异

备注:下文基于PHP主流php-fpm模式。
对比项 PHP Go
字符串表示 单引号(PSR) 双引号
拼接字符串 . +
语言版本兼容性 不好 向下兼容
代码风格 无官方标准,社区标准起步晚 自始至今官方统一标准,且提供工具
脚本语言 不是
强类型语言 不是(PHP7支持严格模式)
是否支持垃圾回收
面向对象语言(OOP) 神似 部分支持,核心是合成复用
是否支持继承 否(有合成复用)
是否支持interface
是否支持try...catch...
是否支持包管理
是否支持跨平台
环境搭建成本
执行方式 cli命令行模式、php-fpm模式(①) 二进制
进程模型 多进程 单进程
原生是否支持创建TCP/UDP服务 是(支持不好,生产不可用)
原生是否支持创建HTTP服务 是(支持不好,生产不可用)
进程阻塞性
是否支持协程 否(②)
并发能力(③) 极强
是否常驻内存运行 不是(④)
引入文件方式 require或者include对应文件 import导入包
是否支持单元测试
是否支持基准测试(benchmark)
是否支持性能分析 支持(xhprof/tideways) 支持(pprof/dlv)
性能分析工具使用成本 高(装扩展成本高) 极低
①其他模式还有swoole等
②PHP的swoole协程框架等支持协程
③此处不考虑I/O多路复用,PHP的swoole协程框架等也支持协程并发
④PHP的swoole协程框架是常驻内存,cli命令行模式也可以常驻内存等

刚开始由PHP语言转Go语言的过程,重点是编程意识的转变,尤其是以下几点:

  • 强类型

  • 常驻内存运行

  • 理解和使用指针

  • 并发安全

  • 资源及时释放或返还

基础语法差异

备注:下文基于PHP5.4+版本

常用基本类型对比

PHP类型比较少和简单,PHP常用数据类型有boolean布尔值、string字符串、int整型、float浮点型、array数组、object对象。

PHP常用数据类型和Go语言对应或者类似的类型做个对比,如下:

语言\类型 boolean string int float array object
PHP bool string int float array(1,2,3)索引数组、array('1' => 1, '2' => 2, '3' => 3)关联数组 实例化类class
Go bool string int、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64 float32、float64 [length]type 比较像struct

除此之外Go还支持更丰富的类型:

类型
slice切片(相当于PHP的索引数组)
map(相当于PHP的关联数组)
channel(管道,通过通信共享,不要通过共享来通信)
指针(Go语言的值类型都有对应的指针类型)
byte(字节,对应uint8别名,可以表示Ascaii码)
rune(对应int32,可以表示unicode)
等等
自定义类型,例如type userDefinedType int32

常用基本类型初始化方式对比

类型 PHP Go(定义变量带var关键字,或者不带直接使用语法糖:=)
boolean $varStr = true; var varStr bool = true
或者 var varStr = true
或者 varStr := true
string $varStr = 'demo'; var varStr string = ""
或者 varStr := ""(:=写法下面省略)
int32 $varNum = 0; var varInt32 int32 = 0
int64 同上 var varInt64 int64 = 0
float32 $varNum = 0.01; var varFloat32 float32 = 0
float64 同上 var varFloat64 float64 = 0
array $varArray = array();
或者语法糖$varArray = [];
var varArray [6]int32 = [6]int32{}
slice(切片) 同上,PHP叫索引数据 var varSlice []int32 = []int32{}切片相对于数据会自动扩容
map $varMap = array('key' => 'value'); var varMap map[string]int32 = map[string]int32{}
closure(闭包) $varClosure = function() {}; var varClosure func() = func() {}
channel var varChannel chan string = make(chan string) 无缓存channel;
var varChannelBuffer chan string = make(chan string, 6)有缓存channel

PHP类的实例化和Go结构体的初始化的对比

PHP类的实例化

/* 
定义class
*/
class ClassDemo {
    // 私有属性
    private $privateVar = "";
    // 公有属性
    public $publicVar = "";
    // 构造函数
    public function __construct()
    {
        // 实例化类时执行
    }
    // 私有方法
    private function privateFun()
    {
    
    }
    // 公有方法
    public function publicFun()
    {
    
    }
}

// 实例化类ClassDemo 获取类ClassDemo的对象
$varObject = new ClassDemo(); // 对象(类)

Go结构体的初始化

// 包初始化时执行
func init() {

}

type StructDemo struct{
    // 小写开头驼峰表示私有属性
    // 不可导出
    privateVar string
    // 大写开头驼峰表示公有属性
    // 可导出
    PublicVar string
}

// 小写开头驼峰表示私有方法
// 结构体StructDemo的私有方法
func (demo *StructDemo) privateFun() error {
    return nil
}

// 大写开头驼峰表示公有属性
// 结构体StructDemo的公有方法
func (demo *StructDemo) PublicFun() error {
    return nil
}

// 初始化结构体StructDemo
// structDemo := &StructDemo{}

常用函数对比

常用函数描述 PHP Go
数组长度 count() len()
分割字符串为数组 explode() strings.Split(s string, sep string) []string
转大写 strtoupper() strings.ToUpper(s string) string
转小写 strtolower() strings.ToLower(s string) string
去除空格 trim() strings.Trim(s, cutset string) string
json序列化 json_encode() json.Marshal(v interface{}) ([]byte, error)
json反序列化 json_decode() json.Unmarshal(data []byte, v interface{}) error
序列化(不再建议使用) serialize()、unserialize() 包https://github.com/wulijun/go-php-serialize
md5 md5() 包crypto/md5
终端输出 echo、var_dump等 fmt.Println(a ...interface{})
各种类型互转 intval()等 包strconv

避坑指南

  1. 谨慎使用全局变量,全局变量不会像PHP一样,在完成一次请求之后被销毁

  2. 形参是slice、map类型的参数,注意值可被全局修改

  3. 资源使用完毕,记得释放资源或回收资源

  4. 不要依赖map遍历的顺序

  5. 不要并发写map

  6. 注意判断指针类型不为空nil,再操作

  7. Go语言不支持继承,但是有合成复用

1. 谨慎使用全局变量,全局变量不会像PHP一样,在完成一次请求之后被销毁

package main

import (
	"github.com/gin-gonic/gin"
)

// 全局变量不会像PHP一样,在完成一次请求之后被销毁
var GlobalVarDemo int32 = 0

// 模拟接口逻辑
func main() {
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		atomic.AddInt32(&GlobalVarDemo,1)
		c.JSON(200, gin.H{
			"message": GlobalVarDemo,
		})
	})
	r.Run()
}

// 我们多次请求接口,可以很明显发现:全局变量不会像PHP一样,在完成一次请求之后被销毁。
// 但是PHP不一样,全局变量在完成一次请求之后会被自动销毁。
// curl "127.0.0.1:8080/ping" 
// {"message":1}                                                                     
// curl "127.0.0.1:8080/ping"
// {"message":2} <------- 值在递增
// curl "127.0.0.1:8080/ping"
// {"message":3} <------- 值在递增

2. 形参是slicemap

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值