PHP 基础知识(更新中)

php中static和const关键字用法分析
1.const是类中的常量,类外用define来定义常量
2.const只可以修饰类的属性,不能修饰类的方法,static可以修饰属性,也可以修饰方法
3.const和static都属于类本身,而不属于new后的类实例.类内访问使用self::,类外使用类名::来访问;类内的$this指代类实例本身,const和static属于类本身,所以无法用$this访问
4.self::NAME指代const,self::$name指代static;const是常量,是不需要变量符号的.static修饰的变量,需要变量符.
5.const一旦被定义不可更改,static修饰的变量是可以被更改的
6.static方法中,不能使用类的普通成员和方法;这很好理解,调用静态方法的时候,不能肯定类有没有被实例化.类的普通方法中可以使用static属性和static方法.
PHP版本差异
PHP8的特性
1、jit即时编译器。jit在opcache优化之后的基础上,结合runtime的信息再次优化,直接生成机器码。jit不是opcache优化的代替,是增强。
2、match表达式,用于变量的值转换与赋值。
3、联合类型。
支持声明并接受多个不同类型的,它是两种或多钟类型的集合。
4、static返回类型。PHP 8 中支持 static 返回类型将更加高效。
5、弱映射WeakMap。允许数组中的key放入对象。
6、类的变更、使用
● 可变参数继承(鸡肋),允许
● 后期静态绑定(LSB)(有用),对框架级别的封装、一些工厂设计模式有用。
● 现在可以使用以下方法获取对象的类名称
● 现在,new 和 instanceof 可以与任意表达式一起使用,使用new(expression)(… $args) 和 $obj instanceof(expression)。
● 现在允许写。
● 添加 Stringable 接口(作用一般,用在视图模板封装)。
● trait 现在可以定义抽象的私有方法。
PHP7的新特性(与PHP5区别)
1、标量类型声明和返回值类型声明。
2、null合并运算符(??)
3、命名空间引用 use 加强:从同一 namespace 导入的类、函数和常量现在可以通过单个 use 语句 一次性导入了
4、匿名类:现在支持通过new class 来实例化一个匿名类
5、性能比php5提升2倍。
6、支持64位。
为什么php7比php5性能提升了?
1、变量存储字节减小。减少内存占用,提升变量操作速度
2、改善数组结构。数组元素和hash映射表被分配在同一块内存里,降低了内存占用、提升了 cpu 缓存命中率
3、改进了函数的调用机制。通过优化参数传递的环节,减少了一些指令,提高执行效率
PHP7执行流程
PHP 代码 => Token => 抽象语法树 => Opcodes => 执行
词法分析,把源代码切割成多个字符串单元(Token)
语法分析器把Token转换成AST抽象语法树
抽象语法树转换成opcodes(opcode指令集合)
虚拟机解释执行执行opcodes(opcode是一组指令标识,对应handler处理函数)
PHP7 内核架构

php的运行模式有两种:web模式和cli模式
php的工作原理:Sapi
Sapi全称是Server Application Programming Interface,也就是服务端应用编程接口,Sapi通过一系列钩子函数,使得PHP可以和外围交互数据,这是PHP非常优雅和成功的一个设计,通过sapi成功的将PHP本身和上层应用解耦隔离,PHP可以不再考虑如何针对不同应用进行兼容,而应用本身也可以针对自己的特点实现不同的处理方式。
php 生命周期
4个关键调用

SAPI运行PHP都经过下面几个阶段:
1、模块初始化阶段(module init):
这个阶段主要进行php框架、zend引擎的初始化操作。这个阶段一般是在SAPI启动时执行一次,对于FPM而言,就是在fpm的master进行启动时执行的。php加载每个扩展的代码并调用其模块初始化例程(MINIT),进行一些模块所需变量的申请,内存分配等。
2、请求初始化阶段(request init):
当一个页面请求发生时,在请求处理前都会经历的一个阶段。对于fpm而言,是在worker进程accept一个请求并读取、解析完请求数据后的一个阶段。在这个阶段内,SAPI层将控制权交给PHP层,PHP初始化本次请求执行脚本所需的环境变量。
3、php脚本执行阶段:
php代码解析执行的过程。Zend引擎接管控制权,将php脚本代码编译成opcodes并顺次执行
4、请求结束阶段(request shutdown):
请求处理完后就进入了结束阶段,PHP就会启动清理程序。这个阶段,将flush输出内容、发送http响应内容等,然后它会按顺序调用各个模块的RSHUTDOWN方法。RSHUTDOWN用以清除程序运行时产生的符号表,也就是对每个变量调用unset函数。
5、模块关闭阶段(module shutdown):
该阶段在SAPI关闭时执行,与模块初始化阶段对应,这个阶段主要是进行资源的清理、php各模块的关闭操作,同时,将回调各扩展的module shutdown钩子函数。这是发生在所有请求都已经结束之后,例如关闭fpm的操作。(这个是对于CGI和CLI等SAPI,没有“下一个请求”,所以SAPI立刻开始关闭)
以nginx服务器为例,在web模式下,生命周期流程

PHP的核心架构图

Zend 引擎:Zend引擎为PHP提供了基础服务,包括词法分析 语法分析 ,AST抽象语法树编译 opcodes执行,PHP的变量设计、内存管理、进程管理。
PHP层:绑定了SAPI层并处理与它的通信,它同时对safe_mode和open_basedir的检测提供一致的控制层,将fopen()、fread()和fwrite()等用户空间的函数与文件和网络I/O联系起来。
SAPI:包括了cli fpm等,把接口对外接口都抽象出来,只要遵守SAPI协议便可以实现一个server。
拓展:zend 引擎提供了核心能力和接口规范,在此基础上可以开发拓展

php数据的实现
php数据的底层实现是散列表(也叫hashTable)

PHP 的垃圾回收机制
PHP 可以自动进行内存管理,清除不需要的对象。
PHP 使用了引用计数GC机制。
每个对象都内含一个引用计数器 refcount,每个 reference 连接到对象,计数器加 1。当 reference 离开生存空间或被设为 NULL,计数器减 1。当某个对象的引用计数器为零时,PHP 知道你将不再需要使用这个对象,释放其所占的内存空间。

PHP-FPM 是什么架构模式的?你怎么优化过它?
它是一个master和worker的架构模式,work处理请求,master管理和回收子进程。
优化的话,曾经有更改过它的进程数的配置。

PHP的基本变量类型
四种标量类型 :boolean (布尔型)、integer (整型)、float (浮点型, 也称作 double)、string (字符串)
四种复合类型 :array (数组)、object (对象)、callable、iterable
最后是两种特殊类型 :resource(资源)、NULL(NULL)

PHP魔术方法
PHP 13 个常用魔术方法:
construct、destruct、call 或 __callStatic、get、set、isset、unset、toString、clone、autoload、invoke、sleep、__wakeup

1. __construct
__construct 构造方法,当一个类被实例化创建对象时,会调用构造方法。
2. __destruct
__destruct 析构方法, 当对象在销毁之前或失去对对象的引用时,会调用 析构方法。
3. __call 或 __callStatic
当调用一个未定义的或没有权限的成员方法时,会调用 __call 方法。(当在静态方法中调用一个未定义的或没有权限的成员方法时,则会调用 __callStatic 方法。)

如果本类找不到调用的成员方法,会去父类中找。

如果本类找不到 __call 方法,会去父类中找。
4. __get
当调用一个未定义的或非公有的成员属性时,会调用 __get 方法。
5. __set
当给一个未定义的或非公有的成员属性赋值时, 会调用 __set 方法。
6. __isset
当在一个未定义的或非公有的成员属性上调用 isset函数时,会调用 __isset 方法。
7. __unset
当在一个未定义或非公有的成员属性上调用 unset函数时,会调用 __unset 方法。
8. __toString
在打印输出一个对象时, 会自动调用 __toString 方法。 例: echo 对象名。
9. __clone
当克隆一个对象时, 会自动调用 __clone 方法。 例: $clone_obj = clone 对象名;
10. __autoload
在实例化一个尚未被定义的类时会自动调用 __autoload 来加载类文件。
11. __invoke
当尝试以调用函数的方式调用一个对象时, 会自动调用 __invoke 方法。
12. __sleep
serialize() 函数会检查类中是否存在 __sleep 方法,如果存在,先执行 __sleep 方法,再执行 序列化操作。

<?php
 class User
    {
        public function __sleep(){
            //
  }
    }
    $obj = new User();
    serialize($obj);
  1. __wakeup
    unserialize() 函数会检查类中是否存在 __wakeup 方法,如果存在,先执行 __wakeup 方法,再执行 反序列化操作。
    <?php
    class User
    {
        public function __wakeup(){
            //
    }
    }
    $obj = new User();
    unserialize($obj);
    PHP魔术常量
    PHP 含有 9 个魔术常量。它们的值随着它们在代码中的位置改变而改变

PHP超全局变量
PHP 有 9 个超全局变量:

$_SERVER、$_GET、$_POST、$_REQUEST、$_COOKIE、$_SESSION、$_FILES、$_ENV、$GLOBALS

$_SERVER一个包含了诸如头信息(header)、路径(path)、以及脚本位置(srcipt location)等信息的数组。这个数组中的项目由Web服务器创建。

$_GET 可以获取到使用 get 方法传递的参数的相关信息。
$_POST 可以获取到使用 post 方法传递的参数的相关信息。
$_REQUEST 是一个关联数组,默认包含 $_GET、$_POST、$_COOKIE 中的内容。不建议用这个超级变量,因为它不够安全。
$_COOKIE 是一个关联数组,包含 通过 HTTP cookie 传递给当前脚本的内容。
$_SESSION 是一个关联数组,包含当前脚本中的所有 session 内容。
$_FILES 是一个关联数组,包含通过 HTTP POST 方法上传给当前脚本的文件内容。
$_ENV 是一个包含服务器端环境变量的数组。
$GLOBALS 是一个关联数组, 包含对当前脚本全局 范围内定义的所有变量。

PSR 标准规范

面向对象
● 面向对象分析(Object Oriented Analysis,OOA);
● 面向对象设计(Object Oriented Design,OOD);
● 面向对象编程(Object Oriented Programming,OOP)
面向对象程序设计中的概念主要包括:对象、类、数据抽象、继承、动态绑定、数据封装、多态性、消息传递。
面向对象中两个重要的基本概念就是类和对象
类:是相同种类对象的抽象,是它们的公共属性。
对象:对象是类的实例。
1) 类
类是事物相关属性特征和行为特征的集合。
属性特征: 就是该事物的状态。比如: 用户性别、用户的身高。
行为特征: 就是该事物能够做什么。比如: 用户下单、用户评论。
⚠️ 注意
属性特征在类中被称为: 成员属性或成员变量
行为特征在类中被称为: 成员方法
2) 对象
一个对象有状态、行为和标识三种属性
对象是客户存在的一个实例,是事物的具体实现。可以通过对象调用类的属性 与 行为。
3) 类与对象的关系
● 类是对对象抽象的一个描述
● 对象是客观存在的一个实体
类是对象的抽象,在类中可以定义对象的属性和方法;对象是类的实例,类只有被实例化后才能使用。

面向对象编程的特性
1) 封装
封装就是将一个类的使用和实现分开,只保留有限的接口(方法)与外部联系。对于用到该类的开发人员,只要知道这个类该如何使用即可,而不用去关心这个类是如何实现的。这样做可以让开发人员更好地把精力集中起来专注于别的事情,同时也避免了程序之间的相互依赖而带来的不便。
类的封装性为类的成员提供公有(public)、缺省(默认default)、保护(protected)和私有(private)等访问权限,目的是隐藏类中的私有变量和类中方法的实现细节 。
public : 对所有类可见。使用对象:类、接口、变量、方法
protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
private : 在同一类里可见。使用对象:变量、方法。 注意:不能修饰类(外部类)

2) 继承
继承就是派生类(子类)自动继承一个或多个基类(父类)中的属性与方法,并可以重写或添加新的属性或方法。继承这个特性简化了对象和类的创建,增加了代码的重用性。
继承分为单继承和多继承,PHP 目前只支持单继承(但是也可以通过Trait实现),也就是说一个子类有且只有一个父类。
允许通过继承原有类的某些特性或全部特性而产生全新的类,原有的类称为父类,产生的新类称为子类。子类不仅可以直接继承父类的共性,而且也可以创建它特有的个性。

3) 多态
对象的状态是多变的。一个对象相对于同一个类的另一个对象来说,它们拥有的属性和方法虽然相同,但却可以有着不同的状态。另外,一个类可以派生出若干个子类,这些子类在保留了父对象的某些属性和方法的同时,也可以定义一些新的方法和属性,甚至于完全改写父类中的某些已有的方法。多态增强了软件的灵活性和重用性。
多态是指在基类中定义的属性和方法被子类继承之后,可以具有不同的数据类型或表现出不同行为,多态性有两种表现形式:重载和覆盖,多态最大的特征就是向上造型。

面向过程和面向对象的定义
面向过程(Procedure-Oriented Programming,简称POP)是一种编程模型,由一系列要执行的计算步骤组成,通常采用自上而下、顺序执行的方式。
面向过程的编程语言包括:C、Fortran、Pascal、Basic等。
面向对象编程(Object-oriented programming,简写:OOP)是一种计算机编程模型,它围绕数据或对象而不是功能和逻辑来组织软件设计,更专注于对象与对象之间的交互,对象涉及的方法和属性都在对象内部。说的更底层一点就是面向对象是一种依赖于类和对象概念的编程方式。
面向对象的编程语言包括:C++、Java、Python、C#以及JavaScript等。
面向过程和面向对象的区别
(1)安全性
面向对象比面向过程安全性更高,面向对象将数据访问隐藏在了类的成员函数中,而且,类的成员变量和成员函数都有不同的访问属性。而面向过程并没有合适的方法来隐藏程序数据。
(2)程序设计上
面向过程通常将程序分为一个个的函数,而面向对象编程中通常使用一个个对象来,函数通常是对象的一个方法。
(3)过程
面向过程通常采用自上而下的方法,而面向对象通常采用自下而上的方法。
(4)程序修改
面向对象编程更容易修改程序,更容易添加新功能。
面向过程和面向对象优缺点
面向过程:
优点:效率高,因为不需要实例化对象。
缺点:耦合度高,扩展性差,不易维护(例如:每个步骤都要有,不然就不行)
面向对象:
优点:耦合低(易复用),扩展性强,易维护,由于面向对象有封装、继承、多态性的特点,可以设计出低耦合的系统,使系统更加灵活、更加易于维护。
缺点:效率比面向过程低。
面向对象的七大原则
● 单一职责原则
一个类应仅有一个职责。例: 一个类不能即完成用户的注册, 又完成商品的购买。
● 开放封闭原则
即对扩展开放对修改关闭。通俗的讲就是不修改源代码● 里式替换原则
所有引用基类的地方必须能透明地使用其子类的对象。通俗的讲就是 子类可扩展父类, 而不是覆盖父类或改变父类原有的功能。
● 依赖倒置原则
依赖于抽象
通俗的讲:
1. 高层次模块不应该依赖于低层次模块,两者都应依赖于抽象
2. 抽象不应该依赖细节,细节应该依赖于抽象。
● 接口隔离原则
使用多个小且专门的接口, 不要使用一个大的总接口。
通俗的讲就是: 不要把所有功能都写在一个接口中,干啥的就是干啥的,且不应该依赖那些不需要用不着的接口。
● 迪米特原则
降低类与类之间的耦合。
通俗的讲就是: 没有关系的类别硬往一起扯,减少没用的交际。
● 合成/聚合复用原则
尽量使用对象组合,而不是继承来达到复用的目的。
通俗的讲就是: PHP类之间的关系,尽可能的多使用 trait和 use ,少使用 extends。

类、属性、方法的修饰符
成员方法的修饰符有: public、protected、private、static、abstract、final
属性修饰符有: public、protected、private、static、var (var 与 public 作用相同, var 是 public 的别名。)
类的修饰符有: abstract、final、interface、trait

static 静态修饰符
● static 静态修饰符 : 用于修饰类的成员属性和成员方法 。

static 关键字 : 修饰的成员方法称为静态方法,修饰的成员属性称为静态属性。
调用方法:

可以不用 new(实例化)就可以直接调用, 格式 类名::属性名
静态方法在实例化后的对象也可以访问, 格式 对象名->属性名
⚠️注意:

在静态方法中不可以使用非静态的内容。就是不让使用 $this
在类的方法中可以使用其他静态属性和静态方法,不过要使用self关键字,如 self::静态属性名 或 self::静态方法名

final 修饰符
类使用时: 如果类使用 final关键字修饰时 ,表示这个类不可以有子类,即不能被 继承。
成员方法使用时: 如果成员方法 使用 final 关键字修饰时,表示这个成员方法不可以在子类中被覆盖,即不能被 重写。

abstract 抽象修饰符
类使用时:
抽象类中的成员方法没有方法体,以 (); 结束。
该类不能被实例化
若想使用抽象类,就必须定义一个类去继承这个抽象类,并定义覆盖父类的抽象方法(实现抽象方法)。
<?php
abstract class ClassName{
public function functionName();
}
成员方法使用时:
称为抽象方法,使用关键字 abstract 定义
包含抽象方法的类必须是抽象类,类也要使用关键字abstract加以声明。
<?php
abstract class ClassName{
abstract function functionName();
}
注意 : 含有抽象方法的类肯定是抽象类,但是不是所有的抽象类都必须包含抽象方法。

interface 接口修饰符
假如一个抽象类中所有的方法都是抽象的,那么我们可以使用另外一种方式定义:接口。
接口使用关键字interface来定义,接口中只能有常量与抽象方法。
<?php

# 接口定义格式:

interface interfaceName{

# 常量定义

const USERLEVEL = ‘TOP’;

# 抽象方法定义, 注意抽象方法不需要有 abstract 关键字, 且以 (); 结尾

function funName();
}
<?php

# 接口实现, 定义一个类, 使用 implements 关键字实现

class 类名 implements 接口名1, 接口名2
{

# 必须将 接口 中的所有方法全部重写实现

}

抽象类、派生类、接口之间有何联系和区别
首先,抽象类和接口都包含可以由派生类继承的成员。接口和抽象类都不能直接实例化,但可以声明它们的变量,然后利用多态性把继承这两种类型的对象指定给它们的变量,最后通过这些变量来访问它们的成员,但是不能直接访问派生对象的其他成员。 派生类只能继承一个基类,即只能直接继承一个抽象类,但可以使用一个继承链来包含多个抽象类,而类可以使用任意多个接口。抽象类可以拥有抽象成员(没有代码体,必须在派生类中实现)和非抽象成员(拥有代码体,也可以是虚拟的,以便在派生类中重写),而接口成员则必须在使用接口的类上实现。另外,接口的成员都是公共的,但抽象类的成员则可以是私有的、内部的、受保护的内部成员等。此外,接口不能包含字段、构造函数、析构函数、静态成员或常量。

抽象类和最终类的区别:
1.抽象类可以被继承,并且穿件抽象类就是为了被继承,但是最终类只能实例化;
2.抽象类和最终类都可以被声明使用
3.抽象类可以没有抽象方法,最终类中可以没有最终方法
4.最终类不能被继承,最终方法不能被重写,但是可以被继承
5.抽象类是不能实例化的,实例化必将加载类,然后根本不知道抽象方法的方法体大小,所以不能实例化。

什么是MyBatis

ChatGPT

MyBatis是一种基于Java的持久性框架,用于简化数据库交互。它提供了一种将Java对象映射到关系型数据库中的SQL语句的机制,从而帮助开发者更轻松地进行数据库操作。
以下是一些MyBatis的关键特点和概念:
● 对象关系映射(ORM): MyBatis允许你通过简单的XML或注解将Java对象映射到数据库表,避免了手动编写大量的SQL代码。
● SQL语句的外部化: MyBatis使用XML或注解来定义SQL语句,这使得SQL语句与Java代码分离,提高了可维护性。
● 动态SQL: MyBatis支持动态SQL,允许在运行时构建和改变SQL查询。
● 自动映射: MyBatis能够自动将数据库查询结果映射到Java对象,减少了手动处理结果集的工作。
● 灵活的查询: MyBatis支持各种查询方式,包括简单的CRUD操作、复杂的联合查询,以及存储过程的调用。
● 插件体系: MyBatis提供了插件体系,允许开发者扩展或修改其行为。
● 缓存: MyBatis支持一级缓存和二级缓存,帮助提高查询性能。
● 声明式事务管理: MyBatis可以通过简单的配置来实现声明式事务管理。
使用MyBatis的一般步骤包括配置数据源、定义映射文件(或使用注解)、创建Mapper接口以及使用SqlSession执行数据库操作。
总体而言,MyBatis为Java开发者提供了一种直观、灵活且功能强大的数据库访问方式,使得与数据库的交互变得更加容易和高效。

URI和URL
URI包括URL和URN两个类别,URL是URI的子集,所以URL一定是URI,而URI不一定是URL
URI = Universal Resource Identifier 统一资源标志符,用来标识抽象或物理资源的一个紧凑字符串。
URL = Universal Resource Locator 统一资源定位符,一种定位资源的主要访问机制的字符串,一个标准的URL必须包括:protocol、host、port、path、parameter、anchor。
URN = Universal Resource Name 统一资源名称,通过特定命名空间中的唯一名称或ID来标识资源。

分布式
分布式:服务分散部署在不同服务器组成一个整体应用,分散压力,解决高并发。
分布式部署:系统应用部署在2台以上服务器或虚拟机上,服务间通过RPC、WCF(包含WebService)等交互,即可称作分布式部署。所谓发展趋势微服务也算作分布式的一种。
分布式优点:
  1、将模块拆分,使用接口通信,降低模块之间的耦合度。(解耦合)
  2、将项目拆分成若干个子项目,不同团队负责不同子项目。(项目拆分)
  3、增加功能时只需再加一个子项目,调用其它系统接口即可。(扩展功能)
  4、可灵活进行分布式部署。 
  5、提高代码的复用性,比如service层,如果不采用分布式rest服务方式架构,在手机Wap商城、微信商城、PC、Android、ios每个端都要写一个service层逻辑,开发量大,难以维护和一起升级,此时可采用分布式rest服务方式共用一个service层。
分布式缺点:系统之间交互要使用远程通信,接口开发增大工作量,但利大于弊。
微服务:可单独部署运行的微小服务,一个服务只完成单一功能分散能力,服务之间通过RPC等交互,至少有一个数据库。
用户量过大高并发时,建议将应用拆解为多个子系统,各自隔离,独立负责功能。
微服务缺点:服务数量大,后期运维较难。
集群:多台服务器复制部署相同应用,由负载均衡共同对外提供服务,逻辑功能仍是单体应用。
传统架构:一个程序一个进程一台主机。
缺点:耦合度高,各模块最终要整合在一起,动一发(功能)牵全身升级,扩展性差,不能灵活进行分布式部署。
RPC:Remote Procedure Call,远程过程调用通信,在系统间的主要数据格式以json为主,也有xml的形式,不少老系统仍以xml为主。
分布式和微服务区别:分布式依赖整体组合,是系统的部署方式;微服务是架构设计方式,粒度更小,服务之间耦合度更低。独立小团队负责,敏捷性更高。

Rest
Restful是一种软件架构。REST通过HTTP协议定义的通用动词方法(GET、PUT、DELETE、POST) ,以URI对网络资源进行唯一标识,响应端根据请求端的不同需求,通过无状态通信,对其请求的资源进行表述。而满足Rest的约束条件和原则的框架称为RESTful架构。 Rest架构的主要原则:
1.网络上的所有事物都被抽象为资源
2.每个资源都有一个唯一的资源标识符
3.同一个资源具有多种表现形式(xml,json等)
4.对资源的各种操作不会改变资源标识符
5.所有的操作都是无状态的

Redis
Redis 是一个内存数据库,用作另一个“真实”数据库(如 MySQL 或 PostgreSQL)前面的缓存,以帮助提高应用程序性能。它通过利用内存的高速访问速度,从而减轻核心应用程序数据库的负载
■ 不经常更改且经常被请求的数据
■ 任务关键性较低且经常变动的数据
首次引入持久化时,Redis 是使用快照方式,通过异步拷贝内存中的数据方式来做持久化。不幸的是,这种机制的缺点是可能会在快照之间丢失数据
memcached和redis 两种缓存对比

单个 Redis 实例

Redis 高可用性

Redis 哨兵

Redis 集群

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!