解析型语言与编译型语言不管从性能上,还是从语法上有着较大的差异。
我刚开始从PHP过渡到GO时,无论从语法上还是编程思想上都感觉好别扭,PHP是面向对象的编程思想,而GO更像是面向包的设计思想,所以刚写GO时会经常以PHP编程思维去写代码逻辑,考虑继承考虑多态,其它的下次讲解,今天我举例了几项常见的PHP与GO语法上差异,有兴趣的朋友可以了解一下。
一、变量定义与赋值
这里可以明显突出脚本语言与编译语言的语法差异
PHP:弱类型变量,同一个变量可以随意赋值任何数据类型
$data = 'jack';
$data = 15;
$data = ['name'=>'jack','age'=>15];
GO:强类型变量,变量需预定义,不能随意赋值不同数据类型
var data string = "jack"//预定义变量类型并赋值
data = "ben"
data = 15 //报错:预定义字符串类型,不能再赋值为整型
二、函数定义与回传
Go多值回传比较方便,PHP单值回传某些情况还需判断元素isset($data['nickname'])
PHP:函数只允许单个值回传
function getUser(){
return [
'nickname' => 'Jack',
'city' => 'beijing',
'age' => 15,
];
}
$data = getUser();
echo $data['nickname'],$data['city'],$data['age'];
GO:函数可回传多个值,且传参与回参需定义数据类型
func main() {
nickname,city,_ := getUser()// ’_‘ 选择忽略 忽略
fmt.Println(nickname,city)
}
func getUser() (nickname string,city string,age int) {
return "jack","beijing",15
}
三、阵列(数组)
PHP对数组处理更方便更强大,GO定义多维数组需考虑类型,显得有点繁琐
PHP:定义一个数组变量,无需考虑元素类型任意的多层嵌入赋值
$arr1 = [1,2,3,4,5];
$arr2 = ['a','b','c','d'];
$arr3 = [
'year' => '2022',
'month' => '03',
'day' => '16',
];
$arr4 = [
'jack' => [
'city' => '广州',
'age' => 23
],
'ben' => [
'city' => '深圳',
'age' => 26
],
];
GO:需区分数组(定长)、切片、映射、接口
//数组方式:必须定义长度
arr1 := [5]int{1,2,3,4,5}
//切片方式:无需定义长度,自由扩展
arr2 := []string{"a","b","c","d"}
//映射方式:键与值匹配赋值
arr3 := map[string]string{
"year":"2022",
"month":"03",
"day":"16",
}
//任意类型方式:好长
arr4 := map[string]interface{}{
"jack":map[string]interface{}{
"city":"23",
"age":25,
},
"ben":map[string]interface{}{
"city":"深圳",
"age":25,
},
}
四、抛出异常机制
GO设计初衷就不建议用try catch这种方式捕捉异常,在编译前就应该检查错误,很多人吐槽过这点。
PHP:try和catch可以友好的捕捉代码不规范的异常错误处理
try {
if (1 == 1){
throw new \Exception("抛出异常");
}
}catch (\Exception $e){
echo "捕捉异常:".$e->getMessage();
}
GO:与其它语言不同,panic如果不用recover()会使整个主程序退出不可用
defer func() {
if r := recover(); r != nil {
fmt.Println("捕捉异常",r.(string))
}
}()
if 1 == 1 {
panic("抛出异常")
}
五、判断元素是否存在
PHP比较精简,内置函数判断,GO判断显得有点不太人性化
PHP:简单用in_array与isset即可
$arr1 = ['a','b','c'];
if (in_array('a',$arr1)){
echo "存在";
}
$arr2 = ['name'=>'jack','city'=>'深圳'];
if (isset($arr2['name'])){
echo "存在";
}
GO:切片类型必须用遍历判断,Map映射需回传值判断
arr1 := []string{"a","b","c"}
for _,val := range arr1{
if val == "a" {
fmt.Println("存在")
break
}
}
arr2 := map[string]string{
"name":"jack",
"city":"深圳",
}
if _,ok:= arr2["name"];ok == true {
fmt.Println("存在")
}
六、继承
GO设计思想就不是面向对象的编程,所以没有太多继承与多态,编写思想上需要改变。
PHP:extends关键词继承父类的方法和属性
class person{
protected $action = "";
protected function run(){
return "I can run".$this->action;
}
}
class man extends person{
public function index(){
$this->action = "swimming";
return $this->run();
}
}
GO:struct结构体定义成员属性变量,从而实现继承
type Person struct {
Action string
}
func (p *Person) Run() string{
return "I can run and " p.Action
}
type Man struct {
Person
}
func (m *Man) Index() {
m.Action = "swimming"
m.Run()
}
总结:语法上各有各的优势,下次从性能上给大家讲解一下区别。