PHP转Go之面向对象编程,等等,Go的对象呢?

Go 肯定是面向对象的编程语言,但是在使用起来与传统的面向对象语言总是有点"独树一帜"!本文核心就是将 PHP 中常用的类、函数、继承的概念与 Go 中的做下映射

本文概要

下图对 PHP 中面向对象的一些方式与 Go 中做了简单的映射

没有类的 Go,如何找到对象呢?

在 Go 中,并不存在类这个概念,写惯了 php or java 的工程师,可能对此非常不适应,Go 其实是大量借鉴 c 语言的特性,在 c/c++中,就存在结构体(struct)这个概念,类是对具有相同属性和行为对象的一个抽象,这个抽象可以称作类,自然也可以称作为结构体,新兴的语言比如Go & Rust等,都抛弃了类这个概念,而是通过扩展结构体的能力,而达到面向对象的目的。 例如:

Golang 复制代码
// persion/persion.go
package persion

type Person struct {  // 定义一个结构体,约等于 php 中的类
    Name string       // 公共变量,首字母大写
    City string       // 公共变量,首字母大写
    age  uint8        // 私有变量,首字母小写,对于私有变量仅仅是相同 package 下才可访问
}
// 这里定义了结构体的方法,同样如果以小写字母开头则表示为私有方法,外部不可访问
func (p *Person) GetName() string  { 
    return p.Name
}

func (p *Person) GetAge() uint8  {
    if p.age > 18 {
        return 18
    }
    return p.age
}

func New() *Person {
    return &Person{Name: "小能", City: "北京", age: 35}
}
// main.go
package main

import (
    "fmt"
    "persion"
)

func main()  {
    p := persion.New()
    // 可以通过变量直接访问公共变量,或者通过结构体提供的函数
    fmt.Println("姓名",p.GetName(),p.Name, "年龄", p.GetAge())
    // 私有变量仅可通过结构体暴露的方法来访问,直接访问则编译不通过
    // fmt.Println("姓名",p.Name, "年龄", p.age)  // 这一行会直接报错
}

总结:Golang 通过定义结构体,来实现了类的概念,并通过结构体内变量 or 方法首字母的大小写来控制变量和方法是 public or private

找到对象了,那如何实现对象的继承呢?

PHP 中可以通过基类(父类)和派生类(子类)的方式实现继承,Golang 中则是结构体的组合(composition)概念,即将一个结构体嵌入到另外一个结构体

Golang 复制代码
// persion/man.go
package persion

type Man struct {
    Person          // 继承了整个 Person 结构体的变量及方法
    Watch string
}

func (p *Man) GetAge() uint8 { // 重写了 GetAge 方法,作为一个 Man,没必要隐藏年龄
    return p.age
}

func NewMan() *Man {
    return &Man{
        Person: Person{        // 对于结构体复用,
            Name: "男人",
            City: "北京",
            age:  35,
        },
        Watch: "Mi Watch",
    }
}
// main.go
package main

import (
    "fmt"
    "persion"
)

func main()  {
    m := persion.NewMan()
    // output: 姓名 男人 男人 年龄 35,显然获取年龄是 Man 中定义的新方法
    fmt.Println("姓名",m.GetName(),m.Name, "年龄", m.GetAge()) 
}

那又如何实现多态呢?

在 PHP 中,多态可以借助基类和派生类来实现,除此之外,PHP 中也可以定义接口来实现多态,只需要类在实现时实现接口中定义的所有方法即可

PHP 复制代码
<?php
interface Animal {
    public function Speak();
}

class Dog implements Animal {
    public function Speak() {
        echo " 汪汪";
    }
}

class Cat implements Animal {
    public function Speak() {
        echo "喵喵";
    }
}

$dog = new Dog();
$cat = new Cat();

function animalSound(Animal $animal) {
    $animal->Speak();
}

animalSound($dog); // 输出: 汪汪
animalSound($cat); // 输出: 喵喵

同样在 Golang 中也是通过 interface 来实现多态,不过它比 PHP 语法更简约,连 implements 都省了,而是说只要你的结构体实现了对应 interface 定义的方法,默认就算是该接口的实现:

Golang 复制代码
package main
import "fmt"
// 定义一个 Animal 接口
type Animal interface {
    Speak()
}
// 定义 Dog 结构体,实现 Animal 接口
type Dog struct{}
func (d Dog) Speak() {
    fmt.Println("汪汪")
}
// 定义 Cat 结构体,实现 Animal 接口
type Cat struct{}
func (c Cat) Speak() {
    fmt.Println("喵喵")
}
func animalSound(animal Animal) {
    animal.Speak()
}
func main() {
    // 创建 Dog 和 Cat 对象
    dog := Dog{}
    animalSound(&dog)

    cat := Cat{}
    animalSound(&cat)
}

方法(Methods)和函数(Functions)的区别

需要注意的是,Golang 中跟类型关联的函数称之为方法(Methods),而函数(Functions)是完全独立的

Golang 复制代码
type Dog struct{}
func (d Dog) Speak() { // 这是方法,方法名前面指定该方法应该作用于哪种类型
    fmt.Println("汪汪")
}

经过上面的讲解你是否对 Golang 的面向对象编程有了初步的认知呢?

下一章:继续讲解下 Golang 中的函数和方法

相关推荐
小白跃升坊5 小时前
PHP2Shell:AI 两天挖出 9.2 分漏洞,让全球 70% 网站连夜打补丁!1Panel 已经把修复版本封装好,推到了你的应用商店里。
php·开源安全·1panel·ai安全·漏洞披露
Json____8 小时前
PHP 突发严重安全漏洞,AI 开始改变网络安全的攻防方式
人工智能·web安全·php·it学习·wwwoop.com
catchadmin8 小时前
PHP 8.7 协程新提案 让跨协程代码共享请求身份
开发语言·php
Web极客码9 小时前
我用 Claude 分析 Redis 哨兵日志,实现跨机房数据不一致自动对齐
数据库·redis·php
xuefeiniao10 小时前
PHP2Shell漏洞修复
运维·服务器·php
ServBay10 小时前
AI说代码没漏洞?马上被 PHP 打脸了
aigc·php·ai编程
tq108612 小时前
对PHP漏洞的思考
php
wangruofeng12 小时前
黑色十月:AI 找到的漏洞,两小时数十万次利用
人工智能·安全·php
用户40158233246213 小时前
对话一长,AI 就忘了你说过的话?Claude Code、Codex、Aider、WES Code 怎么压缩上下文
人工智能·go·ai编程
陌陌龙15 小时前
【紧急预警!PHP 核弹级漏洞 php2shell】
开发语言·php