ywp-open / notes Goto Github PK
View Code? Open in Web Editor NEW想法&碎碎念
想法&碎碎念
在 react
中DOM
元素如<button>
的props
是特定形式onClick
如<button onClick={handleSomething}
对于自定义
组件的props
事件形式命名如onSomething,<MyButton onSomething={handleSomething}>
对于处理事件函数命名如handleSomething
文件 composer.json
对composer
来说并非是安装包时的依赖文件文件,只能说是说明配置文件,
文件 composer.lock
才是composer
安装包时真正的依赖文件,composer
安装包时也是读取的这个文件
composer install
读取composer.json
生成 composer.lock
,依赖composer.lock
文件依赖内容安装具体的包
一定要把composer.lock
加入版本控制器,在服务器端 composer install
只针对字段是多个数字序列字符串查询匹配,比如 1,2,3,4
一般这种的都是在 比如多个商品 可以所属多个分类的情况下,任意一个分类都可以查出所属的商品。
假如 商品类型id typeid : 1,11,22,33,44 typeid: 21,31,22
如果两边缺少定界符 ‘,’的话,查出来的数据就准确了,例如 查询 typeid:1
like '%1%'
或者 '%1'
还有'1%'
会查出不准确多余的数据
like '%,1,%'
或者 '%1,'
还有 ',1%'
不是查询不到就是有多余不准确的数据
缺少定界符就会出现结果不理想的数据
补全定界符 typeid: ,1,11,12,13,22,33,44, like '%,1,%'
就会查询到想要的数据
序列
只允许用于数字或字符类型
,原因是:它们可以连续,同时编译器在编译期可以检查该序列
是否为空
,字符
和数字
值是 Rust 中仅有的
可以用于判断是否为空
的类型。
rust中的 ::
不是运算符是一种语法 关联
语法 跟一些路径有关 path
例如
模块层级 关联
的层次的结构 std::file::fs, mod1::submod1::submod2::type::func
等等
调用某个模块中的函数 std::function
称为 关联函数
调用某个类型 Trait,struct等
中的函数 Foo::function
也成为 关联函数
::
语法用于关联函数和模块创建的命名空间
双冒号另一种使用条件:
当在一个表达式里有调用 方法或函数时,需要指定泛型参数类型时
需要使用 双冒号 :: 语法
否则 rustc 会认为是比较运算符
obj.method::<i32,i32>();
func::<i32,i32>();
使用 \ 忽略换行符
保持字符串的原样:
r"这里的字符都会保持原样包含转义字符"
如果字符串中包含 ”
号 r#
开头和结尾加 #
r#"可以保持双引号"#
如果还是有歧义,可以继续增加#
,没有限制
`r###"字符串内容"###
go interface 类似这样的存储结构 (itable,data)
或者 (type,data)
第一种表示 interface
有方法集合
interface{
method
method2
method3
}
第二种表示 interface
没有方法集合也就是 interface{}
空接口
每个 interface {} 变量在内存中占据两个字长:一个用来存储它包含的类型,另一个用来存储它包含的数据或者指向数据的指针。
trait object ---- trait对象
必须需要关键字 dyn Trait
[某个trait的定义] 去修饰或说是标注 某个定义的 trait
作为参数,去接受
具体实现了参数指定中的trait的那些个类型。比如:struct enum
等等,这个就叫做 Trait Object
trait
对象执行属于动态分发,当泛型使用 trait bound
时编译器所进行单态化处理:编译器为每一个被泛型类型参数代替的具体类型生成了非泛型的函数和方法实现
。单态化所产生的代码进行 静态分发
Lisp解释器
Lisp解释器首先会查看一下在列表前面是否有单引号。如果有,解释器就为我们给出这个列表。如果没有引号,解释器就查看列表的第一个元素,并判断它是否是一个函数定义。如果它确实是一个函数,则解释器执行函数定义中的指令。否则解释器就打印一个错误消息。单引号告诉Lisp解释器返回后续表达式的书写形式,而不是像没有单引号时那样对其求值。
定义变量 defvar defconst
(defvar test "test")
(defconst const-test "const test")
改变已存在的变量 set setq 这两个函数同时也可以直接定义变量,因为 elisp 编译器检测到这两个函数引用的【符号】不存在时会自动创建变量。
(set 'test "111")
(setq test "222222") setq 会自动给第一个元素添加【‘引号】只是一种便捷的写法
elisp中一个【变量名】会对应一个【符号】,【符号】是elisp环境中的一种数据结构,【变量名】是【符号】这个结构中的【name】,【变量值】是【符号】这个结构中的【value】
count(*)
包括了所有的列,相当于行数,在统计结果的时候,不会忽略列值为 null
count(1)
包括了忽略所有列,用 1 代表代码行,在统计结果的时候,不会忽略列值为 null
count(列名)
只包括列名那一列,在统计结果的时候,会忽略列值为空(这里的空不是只空字符串或者 0,而是表示 null 的计数,即某个字段值为 null 时,不统计
列名为主键, count(列名) 会比 count(1)快
列名不为主键, count(1) 会比 count(列名)快
如果表多个列并且没有主键,则 count(1) 的执行效率优于 count()
如果有主键,则 select count(主键) 的执行效率是最优的
如果表只有一个字段,则 select count()最优。
如果 2 个协程需要通信,必须给2个协程同一个通道(channel)作为参数,channel就像一座桥梁连接着这两个通道(channel)
如果容量是 0 或者未设置,通信仅在收发双方准备好的情况下才可以成功,通道的发送 / 接收操作在对方准备好之前是阻塞的,所以加入发送方提前往通道(channel)
发送数据或者接收方提前去读取通道(channel)
中的数据都会造成死锁
,golang runtime会检测到并panic
终止运行。
如果容量大于 0就是带buffer
的通道(channel)
,通道(channel)
就是相当于异步的了:缓冲满载(发送)或变空(接收)之前通信不会阻塞,元素会按照发送的顺序被接收。
要在首要位置使用无缓冲通道来设计算法,只在不确定的情况下使用缓冲。
Rust
中具备两种内存地址操作方式 &
和 *
两者都是保存 内存地址
,不同在于 &
内存安全操作编译器会进行严格的检查比如
生命周期,可变,不可变
检查, *
则不会用于在 unsafe
代码块中.
&引用是被编译器加了限制的指针
Rust 中的每一个值[都有且仅有]一个被称为其 所有者(owner)的变量
理解了这句话rust
中的变量用来用去基本就明白了
let x = 100
这个值100
的所有权就是变量x
整个程序的生命周期里也只属于x
let y = &x
fn foo(z:&i32){}
foo(&x)
等等一些其他操作,只要不是把所有权移走的。
[100]
这个值的所有权一直都是属于 [x]
的 其他的各种 传值|赋值|用值 都是用的 x
这个变量对外的 [借用]
共享。
[&借用]
只且仅只针对 [变量 x]
,是[变量x自己本身,借用或共享]
出去给另一个变量可以操作数据也就是[值]
的权限,
跟值[100]
没有任何关联的,rust中的值 [有且只能有一个所有者]
。
[所有者]
是一个概念,英文中的 [owner]
在 Linux
中 经常 ls -a
看到的那些目录文件的 [所有者] 一样的理念
[借用]
是一个概念 但在 rust语言
中的实现方式是 &,也是取地址运算符(C语言中指针)
, rust称为 (借用borrow) ,
&expr
出现在表达式前称为 [借用(Borrow)] , &T或&mut T
出现在类型
前称为 借用的指针类型(Borrowed pointer type)
与 C++
中的&
引用不同只是用了同样的 符号(&)
这一个例子
let s = String::from("hello");
s
是[值]
字符串 "hello"
的所有权变量,对的,但这里发生了一次 ”所有权“
转移,”所有权“
转移给了变量[s]
。
String::from()
这个函数中返回的字符串变量,它的”所有权“
转移[move]
给了变量[s]
,
因为它返回的类型不是”&借用指针的类型[&String]“
,而是String
。
修改后:
let s = &mut String::from("hello") == let s: &mut String = &mut String::from("hello")
这时没有发生"所有权"
转移[moved]
,变量[s]”借用“
了 String::from()
这个函数中返回的那个字符串变量,
变量[s]
其实是个指针类型[rust的借用的指针类型”&String“就是指针类型]
,存储着是一个内存地址。
另一个例子:
let s = "hello" IDE 推导类型 let s: &str = "hello",
默认是 "借用的指针(Borrowed pointer type)类型" 型类型, 变量[s] 是一个 "借用的指针(Borrowed pointer type)类型", 存储的是一个内存地址.
个人认为可以理解为, rustc编译器是这样做的
let s = &rustc_var; let rustc_var = "hello"
编译器自动在 变量s 与 字符串"hello" 之间生成了一个中间变量.
对于元组来说,元素个数也是类型的一部分
同一作用域中的资源是以他们声明相反的顺序被释放的。
引用一个变量需要注意对该变量引用时代码的位置顺序,如果有一个引用,引用了一个变量,而那个变量的定义,在某个引用类型的后面会出现错误。
let x: &i32;
let y = 99;
x = &y;
会报错 y 存活时间短。
rust 中一个 '单引号
开头的语法叫做 named lifetime specifier 命名生命周期说明符
用泛型声明来规范生命周期的名称, 紧跟单引号可以自定义一个字符可随意, 'a 'b 'aa 'bb
都可以
fn abc<`aaa>(s1: &`aaa str, s2: &`aaa str) ->&`aaa str{}
需不需添加 named lifetime specifier
跟函数的返回值类型相关联, 假如返回值不是 &
类型, 是不需要 named lifetime specifier
的.
泛型 named lifeti specifier
只要是给 rust
编译器使用的主要是去识别传过来的 引用
的 作用域生命周期
的长短.
rust
的编译器默认有三种 省略模式
当有一个参数时rust编译器会自动加上并判断引用生命周期返回值引用跟参数引用一样
因为引用参数都有自己的引用生命周期,所以每一个参数都需要自己的生命周期,因为传进来的引用值是不一样的,当有多个引用参数时就需要自己手动添加 (泛型 named lifet specifier)
当函数中存在 &self 时返回的引用类型 生命周期就是 &self 的生命周期
self
代表 struct类型
的 实例
它的作用域生命周期还是比较长的.
创建型模式
单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式
结构型模式
适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式
行为模式
横版方法模式、命令模式、迭代器模式、观察者模式、中介模式、备忘模式、解释模式、状态模式、策略模式、职责链模式、访问者模式
行为型模式
关注系统中对象之间的相互交互,研究系统在运行时对象之间的相互通信和协作,进一步明确对象的职责,共有11种模式。
创建型模式
关注对象的创建过程。
结构型模式
关注对象和类的组织。
工厂模式分为
集合和字典很容易混淆,因为它们都是用一对花括号定义的。
当花括号内没有键值对时,那就是是集合了。
集合 不同于列表和字典,集合不会以特定的顺序存储元素。
列表,字典,定义时的数据顺序是固定的,读取使用时是不会改变的。
集合 定义时的数据顺序是不固定的,读取使用时数据顺序是随机的呈现的。
位与--------有零则零
位或---------有一则一
异或----------相同为零,不同为一
按位取反----------零变一,一变零
左移-----------对应十进制乘二的移位次方 1<<10 = 1*2^10
右移-----------对应十进制除二的移位次方 1>>10 = 1/2^10
$loader = require './vendor/autoload.php';
执行psr-0规范
$loader->add('',__DIR__);
add 有两个参数
1、命名空间
2、加载的文件目录
composer
会执行 psr-0 规范
类名如果有下划线的话会自动拆分成目录结构
类名 Example_Class
等于 example\class.php
如果类是在命名空间下的话,命名空间会被识别为,目录层次
use ExampleNamespace\ExampleClass;
加载的文件路径就是 ExampleNamespace\ExampleClass.php
第一个参数 命名空间 不管是否为空 psr-0 规范
,都会根据类的全限定名去加载文件,也就是说如果类是在命名空间中,那么命名空间会被识别成目录层次去加载类文件。
$loader->addPsr4('',__DIR__) or $loader->addPsr4('Example\\Namespace\\',__DIR__);
psr-4规范与psr-0
的区别除了 类名中包含下划线之外,就是命名空间了,
如果 addPsr4
这个方法函数,第一个参数 不为空 ,加载文件时 psr-4
会省略 命名空间的目录层次
use Example\Namespace\ExampleClass;
加载时查找的文件是目录 Namespace\ExampleClass.php
如果 addPsr4
这个方法函数,第一个参数为空
加载时查找的文件是目录 Example\Namespace\ExampleClass.php
如果需要在多个目录下搜索相同的命名前缀,可以用一个数组提供:
{
"autoload": {
"psr-4": {
"First\\": ["src/", "lib/"]
}
}
}
http://www.stroustrup.com/bs_faq2.html#Hungarian c/c++ std/stl/boost命令规范
一条准则 namespace/class 声明时 左大括号不换行, 成员函数定义时 左大括号要换行
std 是 standard 的缩写意思是“标准命名空间”
:: 双冒号 域作用域符
代表 :: 右值被调用者是属于 左值的作用域下的,如左值省略则右值是全局作用域下的
在类中如要调用外部同名的成员变量或者成员函数时使用this 指针
类对象调用类成员函数时编译器默认把当前对象指针隐式传到成员函数中,对象指针在当前类中时调用类中的成员变量或者成员函数不受限制修饰符限制,在类中的成员函数中调用当前类的成员变量或者成员函数时可省略 this 指针,编译器默认会自动附加上。
virtual 关键字 标识某个类成员函数是 虚函数
virtal函数代表 准确标识 只被真正的具体的构建对象识别调用 ,多用于有继承关系时有重载现象时使用
Parent *p = new Child
如果Parent类与Child同名的成员函不用virtual关键字标识,此时调用的不会是Child类的成员函数而是Parent类中的成员函数,包括 析构函数 会造成释放的对象内存不正确,例外:构建函数不受影响,如给构造函数加virtual关键字 编译器会报错
class类类型 可以声明两种形式的变量:对象变量 指针对象变量
在编程语言中凡是被某个类型声明修饰的名字统称为 「变量」,针对 「类类型」这种自定义的类型声明修饰的名字除了可以称为 「变量」外还有两种形式的称呼 「对象」「指针对象」
类中对友元函数的声明,只是指明告诉类可以访问这些函数只是一种对此类来说的一种形式,而不是通常一般意义中说明的同时具备函数原型的函数声明,函数的原型声明需要单独在头文件中再进行一次通常一般意义中说明的一样函数的原型的声明,不做这一步有的编译会报错,有的不会
static内存用来保存局部static对象,类static数据成员,以及定义在任何函数之外的变量。栈内存用来保存定义在函数内的非static对象,分配在静态或栈内存中的对象由编译器自动创建和销毁。对于栈对象,仅在其定义的程序块运行时才存在,static 对象在使用之前分配,在程序结束时销毁
对于unsigned整型溢出,C的规范是有定义的——“溢出后的数会以2^(8*sizeof(type))
作模运算,所以在C/C++中所有基本数据类型的最大值都可以通过 2^(8*sizeof(type))
这个公式计算出最大数值
所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法
任何妄图使用父类指针想调用子类中的未覆盖父类的成员函数的行为都会被编译器视为非法
虚表vtable是位于常量段中 既不在堆上,也不在栈上。虚函数表(vtable)的表项在编译期已经确定,也就是一组常量函数指针。跟代码一样,在程序编译好的时候就保存在可执行文件里面。程序运行前直接加载到内存中即可。而堆和栈都是在运行时分配的。而跟虚函数表对应的,是虚函数表指针(vptr),作为对象的一个(隐藏的)成员,总是跟对象的其他成员一起。如果对象分配在堆上,vptr也跟着在堆上;如果对象分配在栈上,vptr也在栈上
虚函数是运行时动态绑定的,编译时无法展开
当派生类覆盖了基类的同名成员函数时,想调用[基类]的同名函数时 [派生类对象-基类类名-域运算符-成员函数]obj_derived.basic::func
定义的 “普通对象“ 可以无限制访问类中声明的所有 成员变量与成员函数 ,定义的 “const对象” 只能访问类中声明的 const成员变量与成员函数 ,类中声明的 const成员函数是不能调用类中非const成员函数 ,类中声明的 const成员函数可以使用类中的所有成员变量,但是不能修改变量的值
前面使用const 表示返回值为const ,后面加 const表示函数不可以修改class的成员
当基类某个成员函数已声明为 “virtual”函数,当派生类也具有与基类为 “virtual”函数的成员函数 相同的函数名时,派生类的成员函数编译器会自动为其生成 “virtual”函数
只有非静态成员函数才可以成为虚函数,而静态成员函数不能声明为虚函数
多态函数是指在运行期才将函数入口地址与函数名绑定的函数,仅有虚函数才是多态
函数签名包括函数名和函数参数的个数、顺序以及参数数据类型 ,需要注意的是函数签名并不包含函数返回值部分,如果两个函数仅仅只有函数返回值不同,那么系统是无法区分这两个函数的,此时编译器会提示语法错误
函数重载是编译期绑定,它并不是多态
函数覆盖属于运行期绑定,但是要注意如果函数不是虚函数,则无论采用什么方法调用函数均为编译期绑定
函数重载不需要构成继承关系,函数重载主要是应用于两个相同的“函数签名”都处于相同的作用域空间中,比如都是处于“全局空间中”,或者都是处于 “同类空间中-构造函数重载”
纯虚成员函数没有函数体,只有函数声明,在纯虚函数声明结尾加上“=0”表明此函数为纯虚成员函数。包含纯虚成员函数的类即为抽象基类,之所以说它抽象,那是因为它无法实例化,也即无法用于创建对象。
只有类中的虚函数才能被声明为纯虚成员函数,普通成员函数和顶层函数均不能声明为纯虚成员函数。抽象基类可以用于实现公共接口,在抽象基类中声明的纯虚成员函数,派生类如果想要能够创建对象,则必须全部重新定义这些纯虚成员函数。
任意两个不相关的多态类类型之间的转换是不能进行的。
dynamic_cast转换规则,只允许指向派生类对象的指针转换为指向基类对象的指针
C++提供的两个类型转换操作符static_cast和dynamic_cast,static_cast可以用于任何类型的强制类型转换,但是它不保证转换过程中的类型安全,dynamic_cast只能用于多态类类型的转换,而且要求转换的目的类型必须为指针或引用,并且它可以保证转换过程中类型安全。
typeid操作符用于判断表达式的类型,注意它和sizeof一样是一个操作符而不是函数
类定义和函数声明放在头文件中,普通函数和类的成员函数的定义放在源文件中,,声明与定义的区别,声明只有类型标识、名称标识然后分号结束,,定义有执行体也就是有大括号“{…..}”
哪怕执行体是空的
常量指针/常量引用(代表指向的是常量对象) const int *p 或者 int const *p 不能修改指向的对象值 ,,指针常量(指针本身是常量) int * const p 不能改变指针本身存储的地址
在C++中不充许跨域重载
using 声明 与 using 指示
using ns::func using 声明相当于在当前作用域内对 ns 命名空间中的函数 func 重新声明一下 ,如果当前作用域内有同名的函数存在会产生“函数重名”编译冲突
using namespace ns using 指示相当于在当前作用域内 把 ns 命名空间中的函数 func 加载到了当前作用域内 如果当前作域内有同名的函数不会产生冲突会产生函数“重载”,如果“函数签名”完全一样的话也不会产生冲突,会遵循优先使用最近的原则或者显示的指定要使用的函数版本
c++继承体系当中 派生类的对象包含有每个基类的子“对象”(只含部份:非静态的) ,这里的“对象”并不指常规中所指的“对象变量”,而是指的是那分配存储的空间整体的一个说明,派生类的作用域嵌套在直接基类和间接基类的作用域中
文件描述符是系统分配给 文件或者套接字的整数
引用:可以有指针引用int*&p
,但不可以有引用的指针int&*p
在C++标准中,明确规定了普通指针(void*)和普通函数指针、类静态成员函数指针的大小是相同的,因此他们之间可以无损的相互转换。
而成员函数指针并没有这样的约束。所以,并不能保证在所有编译器,所有场景下,都能和void*完成双向转换,甚至不同的类型的类成员函数,还会有不同的大小。
如果你想直接告诉编译器T::iterator
是类型而不是变量,只需用typename
修饰:
template <class T>
void foo() {
typename T::iterator * iter;
// ...
}
这样编译器就可以确定T::iterator
是一个类型,而不再需要等到实例化时期才能确定
定义父类(基类)的指针,运行时可以使用子类实际的成员函数,也就是父类具有了多种“形态”,所谓多态。
捕获列表的最常用的四种形式可以是:
-```
[] 空捕获列表
[name1, name2, …] 捕获一系列变量
[&] 引用捕获, 让编译器自行推导捕获列表
[=] 值捕获, 让编译器执行推导应用列表
- using && typedef 不同[ https://zhuanlan.zhihu.com/p/21264013]( https://zhuanlan.zhihu.com/p/21264013)
- 纯右值(prvalue, pure rvalue),纯粹的右值,要么是纯粹的字面量,例如 `10, true`;
要么是求值结果相当于字面量或匿名临时对象,例如` 1+2`。
非引用返回的临时变量、运算表达式产生的临时变量、原始字面量、Lambda 表达式都属于纯右值
- 将亡值(xvalue, expiring value),是 C++11 为了引入右值引用而提出的概念
(因此在传统 C++中,纯右值和右值是统一个概念),也就是即将被销毁、却能够被移动的值。
拷贝构造函数
用于初始化另一个 class object
Class1 cls1;
Class1 cls2 = cls1; cls1初始化了cls2 此时调用的就是。 copy constructor
拷贝赋值运算符
指的是用一个 class obj 对另一个 class obj 赋值
如:
Class2 cls1;
Class2 cls2;
cls2 = cls1; cls1赋值给cls2 此时调用的就是 copy assignments operator
define中的三个特殊符号:#,##,#@
#define STRCAT(x,y) x##y //连接x和y成一个字符串
#define TOCHAR(x) #@x //给x加上单引号
#define TOSTR(x) #x //给x加上双引号
class A{
public:
string s="qweqetfqw"; //=号初始化[复制构造函数]
vector<int> p = { 0 }; //=号初始化列表
vector<int> p{ 0 }; //初始化列表
//error
vector<int> p(0) //调用的是[普通]构造函数 ,是不能[普通]调用构造函数的所以错误
};
在一个node执行一个文件时,会给这个文件内生成一个 exports和module对象或者说是默认内存地址
file1.js
console.log(exports);
console.log(module.exports);
//output
{}
{}
对于nodejs模块来说始终只接受module.exports
导出的内容
默认情况下module.exports与exports始终指向同一个地址
console.log(module.exports === exports); //true
console.log(module.exports == exports); //true
对象调用的形式对模块添加功能代码
module.exports.b = 'bbbbbbbbbbbb';
exports.a = 'aaaaaaaaaaaaaa'
//output
{ b: 'bbbbbbbbbbbb', a: 'aaaaaaaaaaaaaa' }
{ b: 'bbbbbbbbbbbb', a: 'aaaaaaaaaaaaaa' }
是一样的
如果使用赋值的形式对模块进行添加功能代码时就要注意了
比如
module.exports = {//code here}
或者
exports = {//code here}
这样等于是重新给 module.exports
或exports
各自分配了内存地址,改变了它们原来默认指向的地址,所以module.exports
与exports
就会有不同的内容
module.exports = {a:'aaaa'}
console.log(module.exports) // {a:'aaa'}
console.log(exports) // {}
console.log(module.exports === exports); // false
def super(cls,obj):
mro = obj.__class__.mro()
return mro[mro.index(cls)+1]
cls
代表类,obj
代表继承链最底层那个类的实例:
获取 obj
的 MRO
列表
查找 cls
在当前 MRO
列表中的index
, 并返回它的下一个类,即 mro[index + 1]
当你使用 super(cls, obj)
或者 super()
时,Python
会在 obj
的 MRO
列表上搜索 cls
的下一个类。
super(cls,obj) == super()
python 编译器会自动转换 super() => super(__class__,self)
super()
并不是指调用所谓的父类
而是MRO
链中的下一个类
模块加载
每个模块仅加载和执行一次。注意:重复导入仅返回先前所加载模块的引用。
如果模块中的代码已发生更改需要推出python解释器,重新启动解释器运行代码。
nginx中
location /abc/ {
root /opt/xxx;
}
http://www.com/abc/a.jpg
nginx读取的路径是 /opt/xxx/abc/a.jpg
location /def/ {
alias /opt/xxx/; 结尾必须加 /
}
http://www.com/def/a.jpg
nginx读取的路径是 /opt/xxx/a.jpg
mac 10.15 系统apache 2.4.41
下载PHP最新版本php7.4.8
下载跟系统apache接近的版本但要高于系统版本或者和系统版本一样都可
比如下载apache2.4.43
解压apache2.4.43
cd apache2.4.43
./configure --prefix=/Users/mac/Downloads/apache2.4.43 --oldincludedir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include
prefix参数制定哪都行,主要因为不需要安装,就指向当前目录
brew 解决依赖问题
configure 检测通过后会在support目录中产生一个apxs文件,就是它主要也是因为缺少它,所以虽然系统自带了apache但也无法自己编译新版本php为你我所用
chmod ugo+x support/apxs
修改权限
make
make后会在当前目录下编译出httpd(不用管)
mkdir conf
路径/Users/mac/Downloads/apache2.4.43/conf
复制/Users/mac/Downloads/apache2.4.43/doc/conf
目录下的apache配置文件 粘贴到上面建立的conf目录中
mkdir bin
make install后执行文件都是在bin中 例如:/Users/mac/Downloads/apache2.4.43/bin ,
只做说明不需要执行make install
which httpd
查看路径
ln -s /usr/bin/httpd bin
把系统的httpd软连接到bin目录
解压php-7.4.8
cd php-7.4.8
./configure --with-apxs2=/Users/mac/Downloads/apache2.4.43/support/apxs CPPFLAGS="-I/Users/mac/Downloads/httpd/include -I/Users/mac/Downloads/httpd/os/unix"
增加apache
头文件查找路径,不然会提示找不到 httpd.h os.h
头文件
安装路径,其他需要编译的模块,以自身需求添加
brew 解决依赖问题
make && make install
目录php-7.4.8/libs下libphp7.so
就是apache需要的modules文件
移动放到资深认为合适的路径下
编辑/etc/apache/httpd.conf
LoadModule php7_module xxxxxx/xxxxx/xxxxxx/libphp7.so
sudo apachectl -k stop
sudo apachectl -k start
之后下载的 apache php 源文件不需要就可以 rm -f
了
正常模式下 vim的操作不要死记硬背,手册上说明 vim的一个命令是由
opration(操作符) [number] motion(动作) 组成的, number 是可选项
什么是操作符:当按下那个命令键会在vim右下角显示并会停止等待你下一个操作的叫操作符
比如:d r 不会马上产生操作的都是操作符,d 等待输入一个数字或者直接跟一个动作 w
什么是动作(motion):当按下那个命令键马上会有效果的就是动作(motion)
比如:w x 这样的按下键马上就会跳过单词和删除字符就是一个动作(motion)
到这里基本就明白了vim的命令组合,操作符+[数字]+动作 d11w y11w等等 ,,[数字]+动作 10+w 11+l 等等
[数字]是可选项,可以根据需要增加数字的次数操作。
PHP官方文档 https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2
第一步:
下载 https://github.com/Microsoft/php-sdk-binary-tools
cd 到 php-sdk-binary-tools
执行 phpsdk-vs16-x86.bat(VS2019)
第二步
执行 phpsdk_buildtree xxxxx (xxxxxx是目录名),会在当前目录创建 xxxxxxx/vs16/x64 这样的目录结构,并会自动切换到 此目录(php-sdk-binary-tools/xxxxxxx/vs16/x64)
第三步
下载php源码 git clone https://github.com/php/php-src
cd 到 php-src 目录
执行 phpsdk_deps --update --branch master
此时会下载编译PHP需要的依赖
第四部
buildconf
configure --disable-all --enable-cli --with-shared-all 执行这个命令可以看到都会编译哪些扩展
随后根据自己需要追加需要便于扩展的参数 比如:
configure --disable-all --enable-cli --with-shared-all --with-xxx --enable-xxxxx
第五步
nmake && nmake snap
等待PHP编译完成。。。。。
如果只是编译某个PHP扩展步骤是一样的,只是需要(php-sdk-binary-tools/xxxxxxx/vs16/x64)目录中除了下载了PHP源码目录外,在新建一个目录 pecl(固定的目录名编译时会自动查找这个目录),把需要编译的扩展源码下载到次目录,比如 yaf:
git clone https://github.com/laruence/yaf
随后的操作都是一样的,在PHP源码目录中执行
buildconf
configure --disable-all --enable-cli --with-shared-all --enable-yaf
就会显示变异的模块扩展列表中已存在 yaf.
对于数值 0、空值 None、单引号空字符串 ''、双引号空字符串 ""、空列表 []、空元组 ()、空
字典 {},Python 都会返回 False
println!
返回 ()
称为 单元类型
或 空元组
{}
函数体表达式 默认也是返回 单元类型
或 空元组
rust 中分语句和表达式, 在 表达式
代码的结尾没有 ;
都被视为表达式都会返回值的.
像 if , math,loop,while等
如果在右大括号 }
还有没有 ;
也是会有返回值的.
区分 语句 和表达式:
使用 关键字
去定义一个事物的是 语句
例如 let, struct, impl,fn等
这样
表达式
属于会有产生值或结果的都是 表达式
, 函数调用也是 表达式
foo()
形参的形式区别:
fn fn1(v: String);fn fn1(mut v: String);
这两个函数形参是针对所有权转移的。一个所有权转移过来是不可变的,一个所有权转移过来的直接就是可变的。
fn f1(v: &String); fn fn1(v: &mut String);
这两个函数的形参是针对引用的。
let
vs const
不同
const
不能使用 mut
关键字
const
可以声明成全局变量,也就是可以在函数之外声明
const
值必须是常量表达式,不能是需要在运行时才能产生的值
const
声明的变量必须明确标注变量的类型
类型 *T 的可调用方法集包含接受者为 *T 或 T 的所有方法集
类型 T 的可调用方法集包含接受者为 T 的所有方法
类型 T 的可调用方法集不包含接受者为 *T 的方法
在接口上调用方法时,必须有和方法定义时相同的接收者类型或者是可以从具体类型 P 直接可以辨识的:
指针方法可以通过指针调用
值方法可以通过值调用
接收者是值的方法可以通过指针调用,因为指针会首先被解引用
接收者是指针的方法不可以通过值调用,因为存储在接口中的值没有地址
将一个值赋值给一个接口时,编译器会确保所有可能的接口方法都可以在此值上被调用,因此不正确的赋值在编译期就会失败。
move
闭包会创建新的作用域有属于自己的栈桢,对于本地环境变量来说有一下三种捕获方式:
不可变引用,可变引用,这两种会根据当前本地变量的是否有 mut
来区分,如果是可变引用,绑定到闭包的变量也需要声明成 mut 因为闭包环境中发生了改变,move
转移所有权到闭包环境中。
编译器会自动帮闭包生成它自己的环境struct并实现3个trait ,Fn,FnMut,FnOnce,
区别是 &self,&mut self,self。
闭包内把引用
的本地变量当返回值时会发生移动
语义
当一个函数拥有一个显式生命周期参数,那个生命周期必须跟整个调用这个函数的生命周期一样长.
例如 函数内部使用了本地变量的引用去传参,会提示当前的本地变量存活的时效短,因为传参的引用会自动打上当前函数的生命周期参数标记,本地变量又在函数内部所以提示变量存活周期短
这时就需要使用高阶trait bound限定语法 for<'a>
只针对需要接受引用参数的形参指定引用生命周期,而不是应用整个函数的生命周期参数。
在函数内定义函数在很多其他语言中是不支持的,不过rust支持,这也是rust灵活和强大的一个体现。不过,在函数中定义的函数,不能包含函数中(环境中)的变量,若要包含,应该闭包
?
运算符相当于return
:?
运算符所使用的错误值被传递给了 from
函数,它定义于标准库的 From trait
中,其用来将错误从一种类型转换为另一种类型。当 ?
运算符调用 from
函数时,收到的错误类型被转换为由当前函数返回类型所指定的错误类型.
move
关键字覆盖了 Rust 闭包(Closure)默认保守的借用
实例化 class
时如果 class
后出现了 ()
小括号 例如:new class()
,代表是要明确去调用 类的构造函数的
()
小括号是 调用运算符
可以寓意成 在调用 public class(){}
这个构造函数,,,可以寓意 但不要认为是对等
new class()
语义是 还是 实例化 class
这个类 后面出现了 小括号 “调用运算符”,只是明确的告诉 编译器 要调用那个构造函数而已
因为构造函数是可以重载的
例如
public class (){} ,public class (int){}
C# 与 JAVA 在面向对象完全是不想等的两个概念 C# 才是真正的更 C++ 的 接过 C++的衣钵,JAVA在语法上借鉴了 C/C++语法格式而已。没有在深入学习 C# 之前,被 java是C++的安全版,什么从C++演化而来
这种论调忽悠了这麽多年。JAVA应该更加是 Smalltalk 的进化版吧。
C++的引用 &
被称为一个引用变量是另一个变量的别名,给你的感知是引用变量
在 stack(栈)
不会实际存在,因为引用变量无法输出自己的内存地址。
std::string s1 = "abcdefg"
std::string& s2 = s1
printf("%p",s2) //报错 “格式化要求的是void*,但值是一个std::string”
s2(引用变量)不等于指针
printf("%p",&s1) 和 printf("%p",&s2) 内存地址一样的
其实这是C++编译器在搞事情屏蔽了本应该显示但无法显示的障眼法,好处是使用便捷、安全
比如 不用解引用的语法去获取值,也不允许会存在NULL值的情况下的引用
坏处也很明显容易迷糊。
C++的引用本质就是指针,一个引用变量是一个指针变量,本身存储的值是另一个变量的内存地址 也就是必须是左值 left value
。
引用也可以称为安全指针
rust的引用来看C++引用,这两个本质一致,rust的编译器没设置障眼法而已。
let i1: i32 = 100;
let i2: &i32 = &i1; //&i1 取地址运算符
在go
中一个类型只要拥有了与某个interface
中的函数集合相同的所有函数签名就说明实现
了某个interface
。
type Foo interface{
foo1()
foo2(v1 int)bool
...
}
type Bar struct{
Foo
}
var foo Foo = Bar{}
foo.foo1() //这里运行时会报错的
Bar
匿名嵌入了interfac Foo
,它就拥有了与interface Foo
函数集合中所有函数一样的函数签名,Bar
自动实现了interface Foo
。
这在语法上是正确的,但这样直接运行并有函数调用动作
肯定会报错的,这样的语法形式一般适用于某种设计模式。
所以编译器检测代码时只校验函数签名的。
关于变量、类名:
变量名使用英语,不要用动词,变量名通常建议使用名词,选择的名词需要直接指向该变量的含义;
可以在名词前面添加修饰词来区分相似变量,修饰词可以是形容词
如sortKey
中的sort,也可以是指向更细节的名词,如DataFrame
中的Data
;
如果该变量是基础数据类型,则通常使用名词的单数型式
如果该变量是诸如Array、List、Set这样的数据集合,则通常使用名词的复数形式作为变量名;
类名的命名技巧和变量基本一致,不过类名一般不使用复数。
关于函数名和方法名:
方法命名的核心是动词:很多方法用纯动词来表达,如:concat、match
等;
有些方法名会使用动宾词组:即“动词+作用对象名词”的形式。值得一提的是,这里的名词在逻辑上也往往可以是方法后面的参数,如:hasNext、trimEnd,这里的Next和End逻辑上也可以是has和trim的参数;
活用介词:介词是英语的一大特色,在我们给变量起名的时候也扮演了重要的角色,大量地出现在方法名中,如:startsWith、charAt等;
有些方法是以动名词的形式出现:通过动词向'er'、'ing'、'ed'的变形来命名方法。
这类方法名的一大特点是,指向的结果往往是一个对象实例,常见的如constructor、cheching等;
最后一种方法名,就是纯名词的形式:这种方法通常是输出和获取该对象中某个特定的属性或者变量,这种命名方式本质上就是命名变量,可以参考上文对变量的命名,如:keys、items等。
其它技巧
熟练使用局部变量和作用域:有时候同一个变量名会在多处用到,且指向的含义不同。这时候,熟练掌握局部变量和作用域就非常必要了,这让这些相近概念的变量有了使用同一个变量名的可能性,且不会相互影响。
常见的例子有for循环中的变量i,就是利用了局部变量和作用域的特性。不过这个方法需要对该语言有相当深刻的理解,否则容易出现变量覆盖。
#[derive(Debug)]
struct Cat<'a,T>{ //'a T 就像函数的形参变量名名,在给函数传实参时实参的变量名也是不一样的只是类型一样 两者无需命名成一样的 变量名
name: T,
color: &'a String
}
impl <'aa,E> Cat<'aa,E>{ // 'aa E 就像是给函数传实参时的变量名传递给了struct的 'a T 两者类型一样 一个是生命周期一个是泛型
fn new(name1:E,color1:&'aa String)->Self{
Cat{
name: name1,
color: color1
}
}
}
let cat_name = String::from("tomcat");
let cat_color = String::from("红色");
let cat = Cat::<String>::new(cat_name,&cat_color);
println!("cat = {:?}", cat);
println!("cat.name = {:?},cat.color={:?}",&cat.name,cat.color);
}
新项目或新目录
git init
这时候 会显示一个 master -> origin
但其实在本地并没有真正的存在 master
分支
而且origin也不存在 git remote add origin https://xxxxx
这样origin
在本地就添加了
这时如果操作 git add . git commit -m ''
这时才会真正建立本地分支
还有如果这样操作 git pull
也不会建立本地分支并会提示你 git pull <remote> <branch>
当你重新执行 git pull origin master
就会在本地建立 master分支
直接建立分支 git branch dev 会提示 fatal: Not a valid object name: 'master'.
那怎莫办呢?
git checkout -b dev
显示的提示会从 master -> origin 变成 dev -> origin
接下来的工作就会直接工作在 dev
分支上
./configure --prefix=/usr/local/python312 --with-openssl=/usr/local/openssl111 -with-openssl-rpath=auto
openssl源码安装
./config --prefix=/usr/local/openssl111 --openssldir=/usr/local/openssl111
自指定路径不污染系统版本
_tkinter not found
export TCLTK_LIBS="-ltcl -ltk"
since 3.11
configure 把 --with-tcltk-includes和--with-tcltk-libs这两个参数移除!要求使用 TCLTK_CFLAGS 和 TCLTK_LIBS
增加个不编译 tkinter 才好,服务器端用不到的
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.