├── C语言 ├── static和extern.md ├── typedef.md ├── 变量类型.md ├── 指针.md ├── 指针函数和函数指针.md ├── 数组.md ├── 枚举.md ├── 结构体.md ├── 联合体(union).md └── 预处理指令.md ├── Elastic ├── ReadMe.md └── 集群.md ├── Javascript ├── ES6(let、const、var).md ├── ES6函数拓展.md ├── ES6(set和map).md ├── Ecmascript(for-of).md ├── Es6数字拓展.md ├── JavaScript标准库 │ ├── JavaScript(Date对象).md │ ├── JavaScript(JSON对象).md │ ├── JavaScript(Math对象).md │ ├── JavaScript(Number对象).md │ ├── JavaScript(String对象).md │ ├── JavaScript(object对象).md │ ├── JavaScript(包装对象).md │ ├── JavaScript(属性描述对象).md │ └── JavaScript(数组).md ├── JavaScript面对对象 │ ├── JavaScript面向对象基础.md │ ├── JavaScript(prototype和原型链).md │ ├── JavaScript(原型链).md │ ├── JavaScript(对象和函数关系).md │ └── JavaScript(面向对象编程的特性).md ├── JavaScript(深入系列) │ ├── JavaScript(作用域).md │ ├── JavaScript(变量对象).md │ └── javascript作用域链和.md ├── Javascript(DOM) │ ├── Document节点.md │ ├── Dom(Element对象).md │ ├── Dom(css操作).md │ ├── Dom(elment属性).md │ └── Dom模型概述.md ├── Javascript(get和set).md ├── Javascript箭头函数.md ├── Mysql版本介绍.md ├── Node 和 Element.md ├── composer.json ├── config ├── dva操作.md ├── ecmascript 6.md ├── ecmascript6-笔记2.md ├── es6字符串函数.md ├── javascript基本语法笔记 │ ├── JavaScript(错误处理).md │ ├── Javascript类型转换.md │ ├── Javascript(数组).md │ ├── javascript 编码规范.md │ ├── javascript(函数).md │ ├── javascript(基本类型).md │ ├── javascript(数据类型-对象).md │ └── javascript(运算符).md ├── javascript数据类型.md ├── js深拷贝和浅拷贝.md ├── vue │ ├── Vue cli3配置proxy.md │ ├── Vue-router-linker.md │ ├── Vue-router(构造和信息对象).md │ ├── Vuex介绍.md │ ├── Vue插件.md │ ├── Vue路由.md │ ├── Vue路由钩子.md │ ├── vue(x-template和inline-template)模板.md │ ├── vue-slots.md │ ├── vue3.md │ ├── vue3.provide.md │ ├── vue混合.md │ ├── vue自定义指令.md │ └── vue过渡.md ├── w_h.md ├── 对象解构.md └── 模板字符串.md ├── Laravel ├── 01-LifeCycle.md ├── Blade.md ├── Cache.md ├── Config.md ├── Controller.md ├── Db.md ├── Email.md ├── Events.md ├── Laraval生命周期介绍.md ├── Laravel 技巧.md ├── Laravel[修改AJAX请求中的422].md ├── Laravel源码分析.md ├── LifeCycle.md ├── Middleware.md ├── Notifications.md ├── ORM.md ├── PSR-1.md ├── Queue.md ├── Request.md ├── Response.md ├── Route.md ├── Validation.md ├── View.md ├── auth.md ├── composer.md ├── down.md ├── environment.md └── laravel.png ├── Linux ├── Centos升级git.md ├── C语言指针.md ├── Git学习笔记.md ├── LInux--history命令.md ├── Linux 命令.md ├── Linux【dev-null】.md ├── Linux常用测试命令.md ├── Linux搭建socket服务器.md ├── Llinux (sudouser).md ├── MAC下安装Sqlrv拓展.md ├── Makefile.md ├── Nginx Fpm出现access deny错误.md ├── Nginx location.md ├── Nginx跨域设置.md ├── Shell │ ├── Shell(数组).md │ ├── Shell(接收参数).md │ ├── awk.md │ ├── find命令.md │ ├── grep.md │ ├── linux命令-locate.md │ ├── sed.md │ ├── shell (流程控制).md │ ├── shell(include文件).md │ ├── shell(函数).md │ ├── shell(字符串截取).md │ ├── shell(简介).md │ ├── shell(运算符).md │ └── shell符号.md ├── Sublime-text配置备份.md ├── Ubuntu-soft.md ├── Ubuntu关闭触摸板.md ├── Ubuntu更新ppa.md ├── Ubuntu更新系统.md ├── VIM(设置tab四个空格).md ├── [2018-09-06]分区.md ├── crontab每小时执行一次.md ├── file_stat.md ├── git容易混淆的命令.md ├── git撤销记录.md ├── linux-to-many-open-files.md ├── linuxcomand.md ├── mac date different with linux.md ├── mirrors.md ├── nginx_code.md ├── nginx_log.md ├── nginx负载均衡.md ├── openssl.md ├── sed删除注释行.md ├── svn.md ├── sytemctl自定义服务编写.md ├── 同步,异步,阻塞,非阻塞.md ├── 数据结构-树.md └── 配置多个SSH-Key.md ├── Mysql ├── MySQL_join.md ├── MySQL建议.md ├── Mysql(in、join、exists).md ├── Mysql_autoincrement.md ├── mysql三范式.md ├── mysql分组统计.md ├── sql_mode.md ├── wait_timeout.md └── 算法基础知识.md ├── Nodejs ├── Nodejs--DNS模块.md ├── Nodejs--Os模块.md ├── Nodejs--Path模块.md ├── Nodejs--文件处理.md └── Nodejs-事件对象.md ├── OpenAPI ├── 01-通用信息.md ├── 02-API服务器和基本路径.md ├── 03-媒体类型.md ├── 04-路径和操作.md ├── 05-描述参数.md ├── 06-参数序列化.md ├── 07-描述请求正文(Request).md ├── 08-描述响应(Response).md ├── 09-数据模型(Model).md ├── 10-例子(example).md ├── 11-认证和授权.md ├── 12-组件.md ├── 13-标签分组.md └── Readme.md ├── PHP ├── IIS7下,显示PHP错误(how to display php errors on iis7 or iis7.5).md ├── Laravel │ ├── Laraval生命周期介绍.md │ ├── Laravel 技巧.md │ └── Laravel源码分析.md ├── PHP 7 错误处理.md ├── PHP(SOCKET).md ├── PHPUnit基境.md ├── PHP单元测试.md ├── PHP手册笔记 │ ├── 0.php在unix平台安装.md │ ├── 1.基本语法.md │ ├── 10.错误和异常处理.md │ ├── 2-变量和常量.md │ ├── 3-运算符.md │ ├── 4.流程控制.md │ ├── 5.函数.md │ ├── 6.面向对象(OOP).md │ ├── 7.面向对象(OOP).md │ ├── 8.面向对象(OOP).md │ └── 9.命名空间.md ├── array_column引发的一个问题.md ├── php 反射.md ├── php7.4.md ├── php7匿名类.md ├── phpunit(断言、测试依赖、数据供应器).md ├── php动态添加拓展.md ├── php数组.md ├── php识别条码.md ├── php预定义接口.md ├── swoole │ ├── 1.swoole install.md │ ├── Memory.md │ ├── code │ │ ├── channel.php │ │ ├── client.php │ │ ├── clientServer.php │ │ ├── exec.php │ │ ├── index.html │ │ ├── index.php │ │ ├── pipe.php │ │ ├── process.php │ │ ├── queue.php │ │ ├── server.php │ │ ├── table.php │ │ ├── test.log │ │ └── test.php │ ├── images │ │ ├── 938551899.gif │ │ └── 93855347.gif │ └── swoole_process.md ├── traits.md └── 深入了解php │ ├── zval.md │ └── 第一章(从SAPI开始).md ├── Python ├── Centos安装Python3.md ├── Python 数据结构.md ├── Python(Package).md ├── Python-函数.md ├── Python-数据类型.md ├── Python标准库.md ├── Python模块和包.md ├── Python错误和异常.md ├── Python面向对象.md ├── itertools.md ├── php生成器和迭代.md ├── python(os模块).md ├── python(文件读写).md └── python(shutil 模块).md ├── README.md ├── docker ├── 1.docker安装.md ├── 2.docker 基本操作.md ├── 3.Dockerfile详解.md ├── docker-network.md └── install.sh ├── git ├── Git来管控CRLF和LF混乱局面.md ├── cherry-pick.md ├── git checkout.md ├── git log.md └── worktree.md ├── git忽略文件.md ├── go ├── Map & struct.md ├── Protobuf.md ├── drone.md ├── for-range.md ├── function.md ├── gin.md ├── go 包.md ├── go 数组和切片.md ├── go.mod.md ├── go_.md ├── go_noCloser.md ├── go_throw.md ├── golang byte和rune.md ├── golang标识符.md ├── gopath.md ├── goroutine.md ├── govendor.md ├── json 和struct、map之间的转换.md ├── json.md ├── map&array&struct.md ├── new & make.md ├── note.md ├── package.md ├── struct.md ├── time.md ├── unsafe.md └── 交叉编译.md ├── http_proxy.md ├── redis ├── Redis-Bitmap操作.md ├── Redis-Geo地理位置.md ├── Redis发布订阅.md ├── Redis哈希类型.md ├── Redis字符串.md ├── Redis有序集合.md ├── Redis的alist.md ├── Redis键值命令.md ├── Redis集合set.md ├── SDS.png ├── dict.png ├── intset.png ├── redis列表.md ├── redis开发规则.md ├── redis源码解读-sds.md └── ziplist.png ├── 其他 ├── 2018-09-12.md ├── ANT.md ├── APP多版本服务端兼容.md ├── Xdebug+PHPSTROM.md ├── aes.md ├── clean your code.md ├── images │ ├── 1536130176419.png │ ├── 1536130356026.png │ ├── 1536130606998.png │ ├── 1536130879493.png │ ├── 1536131596474.png │ ├── 1536131722713.png │ ├── 1536131772127.png │ ├── 1536131936983.png │ ├── 1536132188638.png │ ├── 1536132302256.png │ ├── 1536132609448.png │ ├── 1536132748160.png │ ├── 1536133092580.png │ ├── 1536133387168.png │ ├── 1536133451273.png │ ├── 1536133508626.png │ ├── 1536133605461.png │ ├── 1536133804975.png │ ├── 1536133876981.png │ ├── 1536133911407.png │ ├── 1536134070135.png │ ├── 1536134215544.png │ ├── 1536134393112.png │ └── 1536135094157.png ├── make-nginx-follow-symlinks.md ├── maven.md ├── nginx配置ssl出现ERR_SSL_PROTOCOL_ERROR错误.md ├── polipo shadowsocks to http.md └── shadowsocket限速.md ├── 操作系统 ├── 2.操作启动.md ├── 3.操作系统内存管理.md ├── 4.非连续内存分配.md ├── 5.虚拟内存.md ├── 临界区.md ├── 信号量.md ├── 操作系统.md ├── 操作系统概论.md ├── 文件系统.md ├── 管程.md ├── 线程.md ├── 线程同步.md ├── 经典同步问题.md ├── 进程.md ├── 进程控制.md ├── 进程调度.md └── 进程通信.md ├── 整合资源.md ├── 有用的PHPdoc.md ├── 算法和数据结构 ├── 1.数学知识.md ├── 10.插入排序.md ├── 11.堆排序.md ├── 12.归并排序.md ├── 2.算法分析.md ├── 3.链表.md ├── 4.栈.md ├── 5.队列.md ├── 6.(B-tree).md ├── 6.树.md ├── 7.散列.md ├── 8.堆(heap).md ├── 9.排序(冒泡排序).md └── 线性表.md └── 设计模式 ├── PHP依赖注入.md ├── PHP观察者模式.md ├── PHP设计模式.md ├── php工厂模式.md ├── rabbitmq.md └── 设计模式笔记 ├── 01UML.md ├── 02简单工厂模式.md ├── 03-1工厂方法.md ├── 03抽象工厂(abstract factory).md ├── 04单例模式md.md ├── 05观察者模式.md ├── 06建造者模式.md └── code ├── abstractFactory ├── AbstractFactory.php └── ConcreteFactory.php ├── builder ├── Builder.php ├── ConcreteBuilder.php ├── Director.php ├── ProductA.php └── ProductB.php ├── factoryMethod ├── ConcreteFactory.php ├── ConcreteProduct.php ├── FactoryMethod.php ├── Product.php ├── ProductA.php └── test.php ├── observer ├── ConcreteObserver.php ├── ConcreteSubject.php ├── Observer.php └── Subject.php ├── simpleFactory ├── Factory.php ├── Product.php ├── ProductA.php └── ProductB.php └── singleton └── Singleton.php /C语言/static和extern.md: -------------------------------------------------------------------------------- 1 | ## static和extern 2 | 3 | 4 | static和extern 不仅可以修饰变量,也可以修饰函数。 5 | 6 | 外部函数。如果一个文件的函数允许另外文件的函数访问,那么就是一个外部函数。 7 | 8 | 内部函数: 只允许在本文件使用的函数。成为内部函数。 9 | 10 | ### extern 11 | 12 | 默认情况下就是extern 可以省略 13 | 14 | ``` 15 | 16 | extern test(){} // 17 | 18 | extern test();//声明一个函数 19 | ``` 20 | 21 | ### static 22 | 23 | 链接就是把相关的目标文件关联起来。 24 | 25 | 内部函数需要用static 修饰。只能在该文件中使用。 26 | 27 | 28 | 29 | static 定义一个函数。将函数声明为静态函数。 30 | 31 | 32 | 定义静态函数:在函数返回类型前加上static关键字,函数即被定义为静态函数,其特点如下: 33 | 34 | - a.静态函数只能在本源文件中使用 35 | 36 | - b.在文件作用域中声明的inline函数默认为static类型 37 | 38 | 39 | extern 声明一个外部函数。但是extern 可以省略。 40 | 41 | extern表示将变量或函数声明为外部链接,变量默认是内部链接,函数默认是外部链接。因此用来外部链接的函数,声明时有无extern都可以连接通过。而全局变量则不行。通常,在模块的头文件中,对本模块提供给其他模块引用的函数和全局变量以关键字extern声明 -------------------------------------------------------------------------------- /C语言/typedef.md: -------------------------------------------------------------------------------- 1 | ## typedef 2 | 3 | typedef关键字为各种数据类型定义一个新名字(别名) -------------------------------------------------------------------------------- /C语言/变量类型.md: -------------------------------------------------------------------------------- 1 | ## 变量类型 2 | 3 | C语言有丰富的数据类型和运算符,因此计算能力非常强大,计算过程中使用的值一般用变量来存储。变量也是有分类型的,不同类型的变量有不同的存储类型、不同的生命周期、不同的作用域,C语言也提供了一些关键字来设置变量的属性(比如设置存储类型、生命周期) 4 | 5 | .在大型的C程序中,为了分模块进行开发,一般会将函数的声明和定义(即实现)分别放在2个文件中,函数声明放在.h头文件中,函数定义放在.c源文件中 6 | 7 | ### 变量的作用域 8 | 9 | 10 | 11 | #### 局部变量 12 | 13 | 函数内部的变量就是局部变量。形参也是局部变量。 14 | 15 | 作用在自己的函数内部有效。 16 | 17 | 18 | #### 全局变量 19 | 20 | 函数外部定义的变量。作用范围。从定义的位置开始,到源代码结束。被其他函数共享。 21 | 22 | 23 | ### 变量的存储类型 24 | 25 | 变量的存储类型。就是指变量存储在什么地方。普通内存、堆栈、寄存器。变量的类型决定变量的生命周期。 26 | 27 | 自动变量----堆栈 28 | 29 | 静态变量---内存 30 | 31 | 32 | 寄存器变量 --- 寄存器 33 | 34 | 35 | #### 自动变量 36 | 37 | 所有的局部变量都是自动变量。 存放在堆栈。 38 | 39 | 在程序执行到自动变量的代码块时,自动变量被创建。执行完毕被销毁。 40 | 41 | #### 静态变量 42 | 43 | 静态变量是存放在静态内存的。所有的全局变量,被static修饰的局部变量也是静态变量。 44 | 45 | 静态变量的生命周期在程序运行之前创建,始终存在。直到程序结束。 46 | 47 | ``` 48 | 49 | void fn(){ 50 | static a = 10; 51 | a++; 52 | printf("%d \n",a); 53 | } 54 | 55 | main(){ 56 | fn();//11 57 | fn();//12 58 | } 59 | ``` 60 | 61 | ### 寄存器变量 62 | 63 | 寄存器是一个硬件。存放在CPU中。高速存储器。 64 | 65 | 1. 被register 修饰的自动变量 都是寄存器变量。 66 | 2. 自动变量才能是寄存器变量。全局变量和静态局部变量不可以。 67 | 3. 寄存器变量只限int char 和指针类型变量使用 68 | 69 | 生命周期:函数中的寄存器变量在调用时候,存放,释放的时候,释放寄存器。 70 | 71 | 将使用比较频繁的自动变量定义寄存器变量。 -------------------------------------------------------------------------------- /C语言/指针.md: -------------------------------------------------------------------------------- 1 | ## 指针 2 | 3 | 直接引用 4 | 5 | 通过变量名进行赋值。就是直接引用。 6 | 7 | 每个变量在内存中, 有一个内存空间。这个内存空间存放的就是变量的内容。 8 | 9 | 10 | ``` 11 | int a ; 12 | 13 | a =10;// 直接引用 14 | 15 | 16 | 17 | ``` 18 | 19 | 20 | 变量 | 地址|存储的内容 21 | ---|---|---| 22 | a | ox000001| 0000 1010 | 23 | 24 | 25 | 间接引用,通过另外一个变量间接访问该变量的值。就是间接引用 26 | 27 | ``` 28 | 29 | int a = 10; 30 | 31 | //定义了一个指针变量。这个b只能指向int 类型。 32 | int *b; 33 | b =&a; 34 | 35 | ``` 36 | 变量b中存放a的地址。b指向a的地址。 37 | 变量 | 地址|存储的内容 38 | ---|---|---| 39 | a | ox000001| 0000 1010 | 40 | b | ox000002| ox000001 | 41 | 42 | 指针变量 43 | 44 | 存放变量地址的变量。就是指针变量。 45 | 46 | 指针变量是存放变量地址的。不能随便一个常数。 47 | 48 | ``` 49 | int a = 10; 50 | 51 | int *p;//指针未分配 52 | 53 | *p = 20; //错误 指针的地址未指向变量。 54 | 55 | p = &a; //将p指向a 56 | 57 | *p = 20; //正确 p指向了a 然后修改a的存储空间内容。 58 | 59 | printf("%d",*p); 60 | ``` 61 | 62 | 一个函数需要有多个返回值的时候,用指针 63 | 64 | 65 | ``` 66 | int sum(int a , int b,int *p){ 67 | 68 | *p = a-b; 69 | return a+b; 70 | 71 | } 72 | 73 | int s; 74 | int m; 75 | int a= 10; 76 | int b = 5; 77 | sum(a,b,&m); 78 | 79 | ``` 80 | 81 | 一个指针变量占用存储的空间等于操作系统的位数。 -------------------------------------------------------------------------------- /C语言/指针函数和函数指针.md: -------------------------------------------------------------------------------- 1 | 2 | ## 函数指针(指向函数的指针) 3 | 4 | 由于函数也是在内存中间的。所以指针也可以指向。函数的名字 就是函数的地址 5 | 6 | 函数指针,是一个指向函数的指针变量。 7 | 8 | 一个函数是若干语句的集合 , 经编译后存储在函数代码存储区 , 并占有一片连续的存储空间 ,对函数指针只能用函数名赋值而无其他运算 9 | 10 | 11 | ``` 12 | int (*f)(int a, int b); // 声明函数指针 13 | 14 | 15 | //定义一个max函数 16 | int max(int a,int b) 17 | { 18 | 19 | return a>b?a:b; 20 | } 21 | 22 | int(*p1)(int,int);//定义一个函数指针。 23 | 24 | p1 = max;//让p1指向max 25 | 26 | (*p1)(1,2) 27 | 28 | 29 | //回调函数 30 | int test(int (*p)()) { 31 | printf("%d\n",*p ); 32 | // return (*p)(2,3); 33 | } 34 | 35 | test(p1) 36 | 37 | ``` 38 | 39 | ## 指针函数(返回指针的函数) 40 | 41 | 42 | 函数执行后可以带回一个值给主调函数 ,这个值可以是标准类型的各种数据 , 也可以是不同类型的指针数据 ,然后使用这些指针间接的访问相关的数据 43 | 44 | 函数类型 *函数名(形式参数表) 45 | { 函数体 } 46 | 47 | ``` 48 | int *f(){} 49 | 50 | int* f(){} 51 | 52 | ``` -------------------------------------------------------------------------------- /C语言/数组.md: -------------------------------------------------------------------------------- 1 | ## 数组 2 | 3 | 只要某个变量有地址,那么指针也可以指向数组。 4 | 5 | 数组名 赋值给指针,那么指针指向第一个元素。 6 | 7 | 数组定义。定义之后,长度确定。数组是一个常量。地址不可修改。 8 | 9 | 10 | 指针加 是类型长度的加减。 11 | 12 | ``` 13 | 14 | int arr[] = {1,3,4,22}; 15 | int *p = arr; 16 | p+1 // &arr[1] 17 | ``` 18 | 19 | 字符串 20 | 21 | 22 | 字符串可以用数组存放。 23 | 24 | ``` 25 | 26 | char s[] = "hellowold"; 27 | 28 | char *s = "hello";//内部数据不可以更改。 29 | ``` -------------------------------------------------------------------------------- /C语言/枚举.md: -------------------------------------------------------------------------------- 1 | ## 枚举 2 | 3 | 枚举是C语言中的一种基本数据类型,并不是构造类型,它可以用于声明一组常数。当一个变量有几个固定的可能取值时,可以将这个变量定义为枚举类型。 4 | 5 | ### 1. 枚举类型定义 6 | 7 | 一般形式为:enum 枚举名 {枚举元素1,枚举元素2,……}; 8 | 9 | 枚举元素不是变量,而是常数,因此枚举元素又称为枚举常量。因为是常量,所以不能对枚举元素进行赋值 10 | 11 | 枚举元素作为常量,它们是有值的,C 语言在编译时按定义的顺序使它们的值为0,1,2, 12 | ``` 13 | enum Season {spring=0, summer, autumn, winter}; 14 | 15 | ``` 16 | 17 | ### 2. 枚举变量的定义 18 | 19 | 20 | 有3种方式定义枚举变量 21 | 22 | - .先定义枚举类型,再定义枚举变量 23 | 24 | ``` 25 | enum Season {spring, summer, autumn, winter}; 26 | 27 | enum Season s; //常量s 28 | 29 | ``` 30 | 31 | - 定义枚举类型的同时定义枚举变量 32 | 33 | ``` 34 | enum Season {spring, summer, autumn, winter} s; 35 | 36 | ``` 37 | 38 | - 省略枚举类型 39 | 40 | ``` 41 | enum {spring, summer, autumn, winter} s; 42 | 43 | ``` 44 | 45 | ### 3.注意事项 46 | 47 | - 1 C语言编译器会将枚举元素(spring、summer等)作为整型常量处理,称为枚举常量。 48 | - 枚举元素的值取决于定义时各枚举元素排列的先后顺序。默认情况下,第一个枚举元素的值为0,第二个为1,依次顺序加1。 49 | - 也可以在定义枚举类型时改变枚举元素的值 50 | - 没有指定值的枚举元素,其值为前一元素加1 51 | ``` 52 | enum {spring, summer, autumn, winter} s; 53 | printf("%d",spring);//0 54 | #例子2 55 | enum {spring=3, summer, autumn, winter} s; 56 | printf("%d",spring);//3 57 | printf("%d",summer);//4 58 | ``` 59 | 60 | ### 4. 枚举变量的基本操作 61 | 62 | 可以给枚举变量赋枚举常量或者整型值 63 | 64 | ``` 65 | s =3 66 | 67 | for(s=spring;s<=winte;s++){ 68 | printf("%d\n",s); 69 | } 70 | 71 | ``` 72 | 73 | -------------------------------------------------------------------------------- /C语言/联合体(union).md: -------------------------------------------------------------------------------- 1 | ## 联合体(union) 2 | 3 | 个数据需要共享内存或者多个数据每次只取其一时,可以利用联合体(union)。在C Programming Language 一书中对于联合体是这么描述的: 4 | 5 | 1)联合体是一个结构; 6 | 7 | 2)它的所有成员相对于基地址的偏移量都为0; 8 | 9 | 3)此结构空间要大到足够容纳最"宽"的成员; 10 | 11 | 4)其对齐方式要适合其中所有的成员; 12 | 13 | 下面解释这四条描述: 14 | 15 | 由于联合体中的所有成员是共享一段内存的,因此每个成员的存放首地址相对于于联合体变量的基地址的偏移量为0,即所有成员的首地址都是一样的。为了使得所有成员能够共享一段内存,因此该空间必须足够容纳这些成员中最宽的成员。对于这句“对齐方式要适合其中所有的成员”是指其必须符合所有成员的自身对齐方式 16 | 17 | 定义一个联合体 18 | 19 | ``` 20 | union U 21 | { 22 | char s[9]; 23 | int n; 24 | double d; 25 | } u1; 26 | 27 | sizeof(u1) // 16 28 | ``` 29 | 联合体的大小。必须满足两个条件:1)大小足够容纳最宽的成员;2)大小能被其包含的所有基本数据类型的大小所整除。 30 | 31 | ``` 32 | union U1 33 | { 34 | char s[9]; 35 | int n; 36 | double d; 37 | } u1; 38 | u1.n = 10; 39 | int a = checkCPU(); 40 | int *p1 = (int *) &u1; 41 | printf("%d\n",*p1); /*10*/ 42 | u1.s[0] ='h'; 43 | u1.s[1] = 'w'; 44 | u1.s[3] ='\0'; 45 | char *p2 = (char *)&u1; 46 | printf("%c\n",*p2);/*h*/ 47 | printf("%d\n",a); 48 | 49 | ``` 50 | 51 | 52 | 共用体”,在某种程度上类似结构体struct的一种数据结构,共用体(union)和结构体(struct)同样可以包含很多种数据类型和变量。 53 | 不过区别也挺明显: 54 | 结构体(struct)中所有变量是“共存”的——优点是“有容乃大”,全面;缺点是struct内存空间的分配是粗放的,不管用不用,全分配。 55 | 而联合体(union)中是各变量是“互斥”的——缺点就是不够“包容”;但优点是内存使用更为精细灵活,也节省了内存空间 -------------------------------------------------------------------------------- /C语言/预处理指令.md: -------------------------------------------------------------------------------- 1 | # 预处理指令 2 | 3 | 在编译之前替换。 4 | 5 | 预处理指令包含三种:宏定义,文件包含,条件编译 6 | 7 | ## 宏定义 8 | 9 | 数组的长度不能用变量。 10 | 11 | 宏定义以#开始。一般用来定义常量。 12 | 13 | 如果是宏定义里面的宏。被引号包含,那么不会被替换。 14 | 15 | 没有类型定义。 16 | ``` 17 | 18 | #define PI 3.14 19 | 20 | #define sum(a,b) (a+b) 21 | 22 | 23 | ``` 24 | 25 | ## 条件编译 26 | 27 | 在满足条件的时候,才编译 28 | 29 | if条件里只能放宏定义。不能放变量。 30 | 31 | ``` 32 | #if 33 | 34 | #elif 35 | 36 | #endif 37 | 38 | 39 | 40 | 41 | ``` 42 | 43 | ``` 44 | 45 | #if defined() 46 | 47 | 48 | #endif 49 | 50 | #ifdef MAX 51 | 52 | code 53 | #endif 54 | ``` 55 | 56 | ## 文件包含 57 | 58 | 1. <>包含的文件 59 | 60 | ``` 61 | #include 62 | ``` 63 | 直接到c语言函数库所在的目录中寻找文件 64 | 65 | 2. ""包含的文件名 66 | 67 | ``` 68 | 69 | #include "string.h" 70 | 71 | ``` 72 | 保护的文件。会在当前目录中,然后到系统的环境变量中找到。 73 | 74 | 为了防止一个头文件被防止重复包含。 75 | 76 | ``` 77 | #ifndef HEADERS_H_INCLUDED 78 | #define HEADERS_H_INCLUDED 79 | 80 | 81 | 82 | #endif // HEADERS_H_INCLUDED 83 | 84 | ``` 85 | 86 | 注意事项。 87 | 88 | 89 | - -------------------------------------------------------------------------------- /Elastic/集群.md: -------------------------------------------------------------------------------- 1 | ## 集群 2 | 3 | 一个运行中的 Elasticsearch 实例称为一个 **节点**,而集群是由一个或者多个拥有相同 `cluster.name` 配置的节点组成, 它们共同承担数据和负载的压力。当有节点加入集群中或者从集群中移除节点时,集群将会重新平均分布所有的数据 4 | 5 | ### 集群健康 6 | 7 | Elasticsearch 的集群监控信息中包含了许多的统计数据,其中最为重要的一项就是 *集群健康* , 它在 `status` 字段中展示为 `green` 、 `yellow` 或者 `red` 8 | 9 | ```shel 10 | curl -X GET "localhost:9200/_cluster/health" 11 | ``` 12 | 13 | ```json 14 | { 15 | "cluster_name": "elasticsearch", 16 | "status": "yellow", 17 | "timed_out": false, 18 | "number_of_nodes": 1, 19 | "number_of_data_nodes": 1, 20 | "active_primary_shards": 16, 21 | "active_shards": 16, 22 | "relocating_shards": 0, 23 | "initializing_shards": 0, 24 | "unassigned_shards": 15, 25 | "delayed_unassigned_shards": 0, 26 | "number_of_pending_tasks": 0, 27 | "number_of_in_flight_fetch": 0, 28 | "task_max_waiting_in_queue_millis": 0, 29 | "active_shards_percent_as_number": 51.61290322580645 30 | } 31 | ``` 32 | 33 | `status` 字段指示着当前集群在总体上是否工作正常。它的三种颜色含义如下: 34 | 35 | - `green` 36 | 37 | 所有的主分片和副本分片都正常运行。 38 | 39 | - `yellow` 40 | 41 | 所有的主分片都正常运行,但不是所有的副本分片都正常运行。 42 | 43 | - `red` 44 | 45 | 有主分片没能正常运行。 46 | 47 | ### 分片 48 | 49 | 一个分片即使一个底层的工作单元,也就是一个luncene实例,Elasticsearch 是利用分片将数据分发到集群内各处的。分片是数据的容器,文档保存在分片内,分片又被分配到集群内的各个节点里。 50 | 51 | -------------------------------------------------------------------------------- /Javascript/ES6(let、const、var).md: -------------------------------------------------------------------------------- 1 | ## es6 const let 2 | 3 | let const 都是块级作用域 4 | 5 | var 函数级作用。 6 | 7 | let 不能多次并定义。不存在变量提升 8 | 9 | const 定义之后,不能被改重新赋值。 10 | 11 | 12 | var name = 10 13 | let name = 10 //报错。 a已经被定义了 14 | { 15 | let name = "100";// 块级 16 | } 17 | 18 | const a =10 19 | 20 | a = 20 //报错 21 | 22 | 23 | 暂存性死区 24 | 25 | 默认使用const 需要更新变量的值用let,最后使用var 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Javascript/ES6函数拓展.md: -------------------------------------------------------------------------------- 1 | Es6 函数的拓展 2 | 3 | ## 默认值 4 | 5 | function test(a=1,b=2){ 6 | console.log(a) 7 | } 8 | 9 | test() // 1 10 | 11 | function test({a=1,b=2}){ 12 | console.log(a,b) 13 | } 14 | 15 | test() //1 2 16 | 17 | 18 | > 一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域(context)。等到初始化结束,这个作用域就会消失。这种语法行为,在不设置参数默认值时,是不会出现的 19 | 20 | let x = 1; 21 | 22 | function f(y = x) { 23 | let x = 2; 24 | console.log(y); 25 | } 26 | 27 | f() // 1 28 | 29 | ## 剩余参数 30 | 31 | ES6 引入 rest 参数(形式为“...变量名”),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。注意,rest 参数之后不能再有其他参数(即只能是最后一个参数) 32 | 33 | 34 | function test(...arg){ 35 | console.log(arg); 36 | } 37 | 38 | test(1,2,3,4,5,6,7);//[1,2,3,4,5,6,7] 39 | 40 | 41 | ## 扩展运算符 42 | 43 | 扩展运算符(spread)是三个点(...)。它好比 剩余 参数的逆运算,将一个数组转为用逗号分隔的参数序列。 44 | 45 | 46 | let arr = [1,2,4,6] 47 | console.log(...arr) // 1 2 4 6 48 | 49 | 运用拓展运算符 50 | 51 | 1. 合并数组 52 | 53 | 54 | let a = [1,2,3] 55 | 56 | let b = [4,5,6] 57 | 58 | let c = [...a,...b] 59 | 60 | 2. 与解构赋值结合 61 | 62 | const [first, ...rest] = [1, 2, 3, 4, 5]; 63 | first // 1 64 | rest // [2, 3, 4, 5] 65 | 66 | 3. 函数的返回值 67 | 68 | 69 | JavaScript的函数只能返回一个值,如果需要返回多个值,只能返回数组或对象。扩展运算符提供了解决这个问题的一种变通方法 70 | 71 | 4. 字符串 72 | 73 | 扩展运算符还可以将字符串转为真正的数组 74 | 75 | [...'hello'] // ['h','e','l','l',''] 76 | 77 | 78 | 79 | ## name 属性 80 | 81 | 函数的name属性,返回该函数的函数名 82 | 83 | 84 | ## 尾调用优化 85 | 86 | 尾调用(Tail Call)是函数式编程的一个重要概念,本身非常简单,一句话就能说清楚,就是指某个函数的最后一步是调用另一个函数.函数调用自身,称为递归。如果尾调用自身,就称为尾递归 -------------------------------------------------------------------------------- /Javascript/ES6(set和map).md: -------------------------------------------------------------------------------- 1 | ## set和map 2 | 3 | set是一种类似数组的结构,但是里面的每一个元素不重复。 4 | 5 | 通过add方法向 Set 结构加入成员,结果表明 Set 结构不会添加重复的值。 6 | 7 | [2,3,4,5,6] 8 | const set = new Set() 9 | set.add(2) 10 | set.add(2) 11 | console.log(set)//[2] 12 | 13 | // 去除数组的重复成员 14 | [...new Set(array)] 15 | 16 | 17 | Set 结构的实例有以下属性。 18 | 19 | 1. Set.prototype.constructor:构造函数,默认就是Set函数。 20 | 1. Set.prototype.size:返回Set实例的成员总数。 21 | 22 | 23 | Set结构有以下方法 24 | 25 | 1. add(value):添加某个值,返回Set结构本身。 26 | 1. delete(value):删除某个值,返回一个布尔值,表示删除是否成功。 27 | 1. has(value):返回一个布尔值,表示该值是否为Set的成员。 28 | 1. clear():清除所有成员,没有返回值。 29 | 30 | 31 | ### Set结构遍历 32 | 33 | 34 | 35 | Set 结构的实例有四个遍历方法,可以用于遍历成员。 36 | 37 | keys():返回键名的遍历器 38 | values():返回键值的遍历器 39 | entries():返回键值对的遍历器 40 | forEach():使用回调函数遍历每个成员 41 | 42 | ## WeakSet § 43 | 44 | WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。 45 | 46 | 首先,WeakSet 的成员只能是==对象==,而不能是其他类型的值。 47 | 48 | 49 | let weak = new WeakSet() 50 | weak.add({}) 51 | weak.add([1]) 52 | 53 | 54 | ## Map 55 | 56 | JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构) 57 | 58 | const ma = new Map([ 59 | ['name', '张三'], 60 | ['title', 'Author'] 61 | ]); 62 | 63 | map.get('name')//张三 64 | 65 | 66 | ### Map的属性和方法 67 | 68 | 69 | 1. set 70 | 71 | map.set(key,value) 72 | 73 | 2. get 74 | 75 | map.get(key) 76 | 77 | 3. has 78 | 79 | map.has(key)//true or false 80 | 81 | 82 | 4. delete 83 | 84 | map.delete(key) // true or false 85 | 86 | 5. clear 87 | 88 | -------------------------------------------------------------------------------- /Javascript/Ecmascript(for-of).md: -------------------------------------------------------------------------------- 1 | 2 | ## for of 3 | 4 | > for...of语句在可迭代对象(包括 Array, Map, Set, String, TypedArray,arguments 对象等等)上创建一个**迭代循环**,对每个不同属性的属性值,调用一个自定义的有执行语句的迭代挂钩. 5 | 6 | 语法: 7 | 8 | for(i of iterable){} 9 | 10 | - 遍历数组 11 | 12 | 13 | var arr = [10,20,30] 14 | 15 | for(let i of arr){ 16 | console.log(i);//10 20 30 17 | } 18 | 19 | - 遍历 String: 20 | 21 | 22 | let iterable = "boo"; 23 | 24 | for (let value of iterable) { 25 | console.log(value); 26 | } 27 | // "b" 28 | // "o" 29 | // "o" 30 | 31 | 32 | - 遍历Map: 33 | 34 | 35 | let iterable = new Map([["a", 1], ["b", 2], ["c", 3]]); 36 | 37 | for (let entry of iterable) { 38 | console.log(entry); 39 | } 40 | // [a, 1] 41 | // [b, 2] 42 | // [c, 3] 43 | 44 | for (let [key, value] of iterable) { 45 | console.log(value); 46 | } 47 | // 1 48 | // 2 49 | // 3 50 | 51 | 52 | for in 和for ....of、forEach的区别 53 | 54 | for in 是遍历每一个枚举对象的属性。 55 | 56 | for of是遍历每个拥有[Symbol.iterator] 属性的collection对象的每个元素 57 | 58 | forEarch 是遍历每个**数组**的元素. 59 | 60 | 61 | var arr = [10,20,30] 62 | 63 | for(let i of arr){ 64 | console.log(i);//10 20 30 65 | } 66 | 67 | for (let i in arr){ 68 | console.log(i);// 0 1 2 69 | } 70 | 71 | arr.forEach(function(val){ 72 | console.log(val);//10 20 30 73 | }) 74 | 75 | 参考文章:[https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/for...of#for...of与for...in的区别](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/for...of#for...of与for...in的区别 "https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/for...of#for...of与for...in的区别") -------------------------------------------------------------------------------- /Javascript/Es6数字拓展.md: -------------------------------------------------------------------------------- 1 | ## 字符串拓展 2 | 3 | ### 二进制和八进制 4 | 5 | ES6 提供了二进制和八进制数值的新的写法,分别用前缀0b(或0B)和0o(或0O) 6 | 7 | 8 | ### Number.isFinite(), Number.isNaN() 9 | 10 | ES6在Number对象上,新提供了Number.isFinite()和Number.isNaN()两个方法 11 | 12 | Number.isFinite(10) 13 | Number.isNaN('SS') 14 | 15 | 16 | ### Number.parseInt(), Number.parseFloat() 17 | 18 | ES6将全局方法parseInt()和parseFloat(),移植到Number对象上面,行为完全保持不变 19 | 20 | ### Number.isInteger() 21 | Number.isInteger()用来判断一个值是否为整数。需要注意的是,在JavaScript内部,整数和浮点数是同样的储存方法,所以3和3.0被视为同一个值 22 | 23 | ### 安全整数和Number.isSafeInteger() 24 | 25 | avaScript能够准确表示的整数范围在-2^53到2^53之间(不含两个端点),超过这个范围,无法精确表示这个值 26 | 27 | 28 | ## Math对象的扩展 29 | 30 | ES6在Math对象上新增了17个与数学相关的方法 31 | 32 | **Math.trunc**方法 33 | 34 | 用于去除一个数的小数部分,返回整数部分 35 | 36 | - Math.sign() 37 | 38 | - 参数为正数,返回+1; 39 | - 参数为负数,返回-1; 40 | - 参数为0,返回0; 41 | - 参数为-0,返回-0; 42 | - 其他值,返回NaN 43 | 44 | 判断一个数是不是整数 负数 或者 0 45 | 46 | - Math.cbrt() 计算一个数的立方根 47 | - Math.clz32() 返回一个数的32位无符号整数形式有多少个前导0 48 | - Math.fround 返回一个数的单精度浮点数形式 49 | 50 | - Math.hypot() 方法返回所有参数的平方和的平方根 51 | 52 | Math.hypot(3,4) //5 53 | 54 | - Math.sinh(x) 返回x的双曲正弦(hyperbolic sine) 55 | - Math.cosh(x) 返回x的双曲余弦(hyperbolic cosine) 56 | - Math.tanh(x) 返回x的双曲正切(hyperbolic tangent) 57 | - Math.asinh(x) 返回x的反双曲正弦(inverse hyperbolic sine) 58 | - Math.acosh(x) 返回x的反双曲余弦(inverse hyperbolic cosine) 59 | - Math.atanh(x) 返回x的反双曲正切(inverse hyperbolic tangent) 60 | 61 | > ES2016 新增了一个指数运算符(**) 62 | -------------------------------------------------------------------------------- /Javascript/JavaScript标准库/JavaScript(JSON对象).md: -------------------------------------------------------------------------------- 1 | ## JSON 对象 2 | 3 | JSON格式(JavaScript Object Notation的缩写)是一种用于数据交换的文本格式。 4 | 5 | **JSON对值的类型和格式有严格的规定** 6 | 7 | 8 | - 复合类型的值只能是数组或对象,不能是函数、正则表达式对象、日期对象。 9 | - 10 | - 简单类型的值只有四种:字符串、数值(必须以十进制表示)、布尔值和null(不能使用NaN, Infinity, -Infinity和undefined)。 11 | - 12 | - 字符串必须使用双引号表示,不能使用单引号。 13 | - 14 | - 对象的键名必须放在双引号里面。 15 | - 16 | - 数组或对象最后一个成员的后面,不能加逗号 17 | 18 | 19 | ``` 20 | ["one", "two", "three"] 21 | 22 | { "one": 1, "two": 2, "three": 3 } 23 | 24 | {"names": ["张三", "李四"] } 25 | 26 | ``` 27 | 28 | ### JSON.stringify() 29 | 30 | 将一个值转成字符串 31 | 32 | JSON.stringify([1, "false", false]) 33 | 34 | ### JSON.parse() 35 | 36 | JSON.parse方法用于将JSON字符串转化成对象。 37 | 38 | ``` 39 | var o = JSON.parse('{"name": "张三"}'); 40 | o.name // 张三 41 | ``` -------------------------------------------------------------------------------- /Javascript/JavaScript标准库/JavaScript(Math对象).md: -------------------------------------------------------------------------------- 1 | ## Math对象 2 | 3 | > Math是JavaScript的内置对象,提供一系列数学常数和数学方法。该对象不是构造函数,不能生成实例,所有的属性和方法都必须在Math对象上调用 4 | 5 | ### 属性 6 | 7 | - Math.E:常数e。 8 | - Math.LN2:2的自然对数。 9 | - Math.LN10:10的自然对数。 10 | - Math.LOG2E:以2为底的e的对数。 11 | - Math.LOG10E:以10为底的e的对数。 12 | - Math.PI:常数Pi。 13 | - Math.SQRT1_2:0.5的平方根。 14 | - Math.SQRT2:2的平方根 15 | 16 | ### 方法 17 | 18 | - Math.abs():绝对值 19 | - Math.ceil():向上取整 20 | - Math.floor():向下取整 21 | - Math.max():最大值 22 | - Math.min():最小值 23 | - Math.pow():指数运算 24 | - Math.sqrt():平方根 25 | - Math.log():自然对数 26 | - Math.exp():e的指数 27 | - Math.round():四舍五入 28 | - Math.random():随机数 29 | - Math.sin():返回参数的正弦 30 | - Math.cos():返回参数的余弦 31 | - Math.tan():返回参数的正切 32 | - Math.asin():返回参数的反正弦(弧度值) 33 | - Math.acos():返回参数的反余弦(弧度值) 34 | - Math.atan():返回参数的反正切(弧度值) -------------------------------------------------------------------------------- /Javascript/JavaScript标准库/JavaScript(Number对象).md: -------------------------------------------------------------------------------- 1 | ## Number 对象 2 | 3 | Number对象是数值对应的包装对象,可以作为构造函数使用,也可以作为工具函数使用 4 | 5 | ``` 6 | 7 | var n = new Number(1) 8 | type n //object 9 | 10 | Number(true) // 1 11 | ``` 12 | 13 | ### Number对象的属性 14 | 15 | - Number.POSITIVE_INFINITY:正的无限,指向Infinity。 16 | - Number.NEGATIVE_INFINITY:负的无限,指向-Infinity。 17 | - Number.NaN:表示非数值,指向NaN。 18 | - Number.MAX_VALUE:表示最大的正数,相应的,最小的负数为-Number.MAX_VALUE。 19 | - Number.MIN_VALUE:表示最小的正数(即最接近0的正数,在64位浮点数体系中为5e-324),相应的,最接近0的负数为-Number.MIN_VALUE。 20 | - Number.MAX_SAFE_INTEGER:表示能够精确表示的最大整数,即9007199254740991。 21 | - Number.MIN_SAFE_INTEGER:表示能够精确表示的最小整数,即-9007199254740991 22 | 23 | ``` 24 | Number.POSITIVE_INFINITY // Infinity 25 | Number.NEGATIVE_INFINITY // -Infinity 26 | Number.NaN // NaN 27 | 28 | Number.MAX_VALUE 29 | // 1.7976931348623157e+308 30 | Number.MAX_VALUE < Infinity 31 | // true 32 | 33 | Number.MIN_VALUE 34 | // 5e-324 35 | Number.MIN_VALUE > 0 36 | // true 37 | 38 | Number.MAX_SAFE_INTEGER // 9007199254740991 39 | Number.MIN_SAFE_INTEGER // -9007199254740991 40 | 41 | ``` 42 | ### Number 对象实例的方法 43 | 44 | Number对象有4个实例方法,都跟将数值转换成指定格式有关 45 | 46 | 1. toString() 47 | 48 | ``` 49 | (100).toString() // '100' 50 | 51 | ``` 52 | 2. toFixed() 53 | 54 | 将一个数转为指定位数的小数,返回这个小数对应的字符串 55 | 56 | toFixed方法的参数为指定的小数位数,有效范围为0到20 57 | 58 | ``` 59 | 60 | (101).toFiexed(2) //101.00 61 | ``` 62 | 63 | 3. toExponential() 64 | 65 | toExponential方法用于将一个数转为科学计数法形式。 66 | 67 | 4. toPrecision() 68 | 69 | toPrecision方法用于将一个数转为指定位数的有效数字 70 | 71 | (12.34).toPrecision(5) // "12.340" 72 | 73 | -------------------------------------------------------------------------------- /Javascript/JavaScript标准库/JavaScript(String对象).md: -------------------------------------------------------------------------------- 1 | ## String对象 2 | 3 | 4 | ``` 5 | var s = "11" 6 | 7 | var s1 = new String(s) 8 | 9 | type s // string 10 | 11 | type s1 //object 12 | 13 | s1.valueOf === s1 //true 14 | 15 | ``` 16 | ### String.fromCharCode() 17 | 18 | String对象提供的静态方法(即定义在对象本身,而不是定义在对象实例的方法),主要是fromCharCode()。该方法的参数是一系列Unicode码点,返回对应的字符串 19 | 20 | ``` 21 | String.fromCharCode(104, 101, 108, 108, 111) 22 | // "hello" 23 | 24 | ``` 25 | 26 | ### 实例对象的属性和方法 27 | 28 | 1. length 属性 返回字符串的长度 29 | 30 | 2. charAt() 31 | 32 | charAt方法返回指定位置的字符 33 | 34 | ``` 35 | "hello".charAt(0) //h 36 | ``` 37 | 3. charCodeAt() 38 | 39 | charCodeAt方法返回给定位置字符的Unicode码点(十进制表示) 40 | 41 | 4. concat() 42 | 43 | concat方法用于连接两个字符串 44 | 45 | 5. slice(begin,end) 46 | 47 | 截取字符 48 | 49 | ``` 50 | 51 | "hello".slice(0,2) // he 52 | ``` 53 | 54 | 6. substr() 55 | 56 | substr方法用于从原字符串取出子字符串并返回,不改变原字符串。 57 | 58 | substr方法的第一个参数是子字符串的开始位置,第二个参数是子字符串的长度 59 | 60 | 7. indexOf(),lastIndexOf() 61 | 62 | 返回字符串在一个子串的位置 63 | 64 | ``` 65 | "hello".indexOf("h") //0 66 | ``` 67 | 68 | 7. toLowerCase(),toUpperCase() 69 | 70 | toLowerCase方法用于将一个字符串全部转为小写,toUpperCase则是全部转为大写。它们都返回一个新字符串, 71 | 72 | 8. localeCompare() 73 | 74 | > localeCompare方法用于比较两个字符串。它返回一个整数,如果小于0,表示第一个字符串小于第二个字符串;如果等于0,表示两者相等;如果大于0,表示第一个字符串大于第二个字符串 75 | 76 | ``` 77 | 'apple'.localeCompare('banana') 78 | // -1 79 | 80 | 'apple'.localeCompare('apple') 81 | // 0 82 | 83 | ``` 84 | 85 | 9. match 86 | 87 | match方法用于确定原字符串是否匹配某个子字符串,返回一个数组 88 | 89 | ``` 90 | 91 | "hello".match("h") // ["h"] 92 | ``` 93 | 94 | 10. splite 分割字符串 95 | 96 | ``` 97 | "h,2,2,3".splite(',') ['h','2','2','3'] 98 | ``` 99 | 100 | 11. search 101 | 102 | 字符串查找。如果大于0 则是找到了,否则返回-1 -------------------------------------------------------------------------------- /Javascript/JavaScript标准库/JavaScript(包装对象).md: -------------------------------------------------------------------------------- 1 | ## 包装对象 2 | 3 | 包装对象”,就是分别与数值、字符串、布尔值相对应的Number、String、Boolean三个原生对象。这三个原生对象可以把原始类型的值变成(包装成)对象 4 | 5 | ``` 6 | var v1 = new Number(123); 7 | var v2 = new String('abc'); 8 | var v3 = new Boolean(true); 9 | 10 | typeof v1 // "object" 11 | typeof v2 // "object" 12 | typeof v3 // "o 13 | 14 | ``` 15 | 注意事项: 16 | 17 | Number、String和Boolean如果不作为构造函数调用(即调用时不加new),常常用于将任意类型的值转为数值、字符串和布尔值 18 | 19 | ### 包装对象的方法 20 | 21 | 1. valueOf() 22 | 23 | 函数对象的原始值 24 | 25 | ``` 26 | new Number(124).valueOf() //124 27 | ``` 28 | 29 | 2. toString 30 | 31 | 返回实例对应的字符串 32 | 33 | new Number(2).toString() // '2' 34 | 35 | 36 | ### Boolean对象 37 | 38 | 主要用于生成布尔值的包装对象的实例 39 | 40 | ``` 41 | 42 | var b = new Boolean(false) 43 | 44 | 45 | ``` 46 | 47 | 如果不使用new 就表示一个构造 48 | 49 | ``` 50 | Boolean(undefined) // false 51 | Boolean(null) // false 52 | Boolean(0) // false 53 | Boolean('') // false 54 | Boolean(NaN) // false 55 | 56 | Boolean(1) // true 57 | Boolean('false') // true 58 | Boolean([]) // true 59 | Boolean({}) // true 60 | Boolean(function () {}) // true 61 | Boolean(/foo/) // true 62 | ``` 63 | 64 | 双重的否运算符(!)也可以将任意值转为对应的布尔值 65 | 66 | ``` 67 | !!undefined // false 68 | !!null // false 69 | !!0 // false 70 | !!'' // false 71 | !!NaN // false 72 | !!1 // true 73 | !!'false' // true 74 | !![] // true 75 | !!{} // true 76 | !!function(){} // true 77 | !!/foo/ // true 78 | 79 | ``` -------------------------------------------------------------------------------- /Javascript/JavaScript面对对象/JavaScript(原型链).md: -------------------------------------------------------------------------------- 1 | ## js 原型链 2 | 3 | instanceof表示的就是一种继承关系,或者原型链的结构 4 | 5 | Instanceof运算符的第一个变量是一个对象,暂时称为A;第二个变量一般是一个函数,暂时称为B。 6 | 7 | Instanceof的判断队则是:沿着A的__proto__这条线来找,同时沿着B的prototype这条线来找,如果两条线能找到同一个引用,即同一个对象,那么就返回true。如果找到终点还未重合,则返回false。 8 | 9 | ``` 10 | function Person() { 11 | 12 | } 13 | 14 | var person = new Person() 15 | 16 | person.__proto__ === Person.prototype 17 | 18 | Person.prototype.constructor === Person 19 | 20 | 21 | ``` 22 | 蓝色__proto__ 就是js原型链 23 | 24 | person 是一个实例对象。 25 | 26 | ![image](http://images2015.cnblogs.com/blog/787416/201603/787416-20160323103557261-114570044.png) 27 | 28 | ![image](https://github.com/mqyqingfeng/Blog/raw/master/Images/prototype5.png) 29 | 30 | ### 实例与原型 31 | 32 | 当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止 33 | 34 | ``` 35 | function Person(){ 36 | 37 | } 38 | 39 | var person = new Person() 40 | 41 | person.name = '张三' 42 | 43 | Person.prototype.age = 11 44 | 45 | 46 | Object.prototype.sex = '1' 47 | 48 | person.name //张三 49 | 50 | person.age // 11 51 | 52 | person.sex //1 object 原型上的 53 | 54 | ``` 55 | 56 | ![image](http://images2015.cnblogs.com/blog/787416/201603/787416-20160323103622089-1134417169.png) 57 | 58 | ![image](http://images2015.cnblogs.com/blog/787416/201603/787416-20160322110905589-2039017350.png) 59 | 60 | -------------------------------------------------------------------------------- /Javascript/JavaScript面对对象/JavaScript(面向对象编程的特性).md: -------------------------------------------------------------------------------- 1 | ## 面向对象的特性 2 | 3 | ### 构造函数继承 4 | 5 | 第一步是在子类的构造函数中,调用父类的构造函数 6 | 7 | ``` 8 | function Sub(value) { 9 | Super.call(this); 10 | this.prop = value; 11 | } 12 | 13 | ``` 14 | 第二步,是让子类的原型指向父类的原型,这样子类就可以继承父类原型 15 | 16 | ``` 17 | Sub.prototype = Object.create(Super.prototype); 18 | Sub.prototype.constructor = Sub; 19 | Sub.prototype.method = '...'; 20 | 21 | 例子 22 | 23 | function Shape() { 24 | this.x = 0; 25 | this.y = 0; 26 | } 27 | 28 | Shape.prototype.move = function (x, y) { 29 | this.x += x; 30 | this.y += y; 31 | console.info('Shape moved.'); 32 | }; 33 | 34 | // 第一步,子类继承父类的实例 35 | function Rectangle() { 36 | Shape.call(this); // 调用父类构造函数 37 | } 38 | // 另一种写法 39 | function Rectangle() { 40 | this.base = Shape; 41 | this.base(); 42 | } 43 | 44 | // 第二步,子类继承父类的原型 45 | Rectangle.prototype = Object.create(Shape.prototype); 46 | Rectangle.prototype.constructor = Rectangle; 47 | ``` 48 | 49 | ### 封装私有变量 50 | 51 | 1. 封装私有变量:立即执行函数的写法 52 | 53 | 54 | _count为私有属性,外部无法读取到。 55 | 56 | ``` 57 | var module1 = (function () { 58 |  var _count = 0; 59 |  var m1 = function () { 60 |   //... 61 |  }; 62 |  var m2 = function () { 63 |   //... 64 |  }; 65 |  return { 66 |   m1 : m1, 67 |   m2 : m2 68 |  }; 69 | })(); 70 | 71 | ``` 72 | 73 | 2. 模块放大模式 74 | 75 | ``` 76 | var module1 = ( function (mod){ 77 |  //... 78 |  return mod; 79 | })(window.module1 || {}); 80 | ``` 81 | 82 | ### 输入全局变量 83 | 84 | 独立性是模块的重要特点,模块内部最好不与程序的其他部分直接交互。 85 | 86 | 为了在模块内部调用全局变量,必须显式地将其他变量输入模块 87 | 88 | ``` 89 | var module1 = (function ($, YAHOO) { 90 |  //... 91 | })(jQuery, YAHOO); 92 | //显式传入jquery 和yahoo 93 | ``` -------------------------------------------------------------------------------- /Javascript/JavaScript(深入系列)/JavaScript(作用域).md: -------------------------------------------------------------------------------- 1 | ## 作用域 2 | 3 | 作用域是指程序源代码中定义变量的区域。 4 | 5 | 作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。 6 | 7 | JavaScript 采用词法作用域(lexical scoping),也就是静态作用域(函数的作用域在函数定义的时候就决定了) 8 | 9 | ``` 10 | 11 | var value = 1; 12 | 13 | function foo() { 14 | console.log(value); 15 | } 16 | 17 | function bar() { 18 | var value = 2; 19 | foo(); 20 | } 21 | 22 | bar(); //1 23 | 24 | //js使用静态作用域 ,再定义的的时候,foo的作用域就已经确定了。 25 | 26 | 定义foo的时候,foo 内部没有value 往上一级找value 找到全局变量中的value 所以value =1 27 | 28 | ``` 29 | 30 | ## 执行上下文栈 31 | 32 | 当执行到一个函数的时候,就会进行准备工作,这里的“准备工作”,让我们用个更专业一点的说法,就叫做"**执行上下文**(execution context)" 33 | 34 | JavaScript 引擎创建了执行上下文栈(Execution context stack,ECS)来管理多个执行上下文 35 | 36 | 37 | 作用域和执行上下文之间最大的区别是: 38 | 39 | 执行上下文在运行时确定,随时可能改变;作用域在定义时确定,永远不会改变 40 | 41 | 上下文包含了调用时的形参,其中的函数声明与变量(VO), 同时创建活动对象(AO),并将AO压入执行上下文的作用域链的最前端并且包含了this的属性,执行上下文的作用域链是通过正在被调用函数的作用域链得到的(动态) 42 | 43 | 作用域涉及到所被调用函数中的变量访问 44 | 45 | 上下文始终是this关键字的值, 它是拥有(控制)当前所执行代码的对象的引用 46 | 47 | ### 可执行代码 48 | 49 | JavaScript 的可执行代码 有三种 全局代码、函数代码、eval代码 50 | 51 | 52 | [参考资料](http://blog.csdn.net/u013510614/article/details/51920840) -------------------------------------------------------------------------------- /Javascript/JavaScript(深入系列)/javascript作用域链和.md: -------------------------------------------------------------------------------- 1 | js的函数的作用域是在创建的时候,就已经建立的。 2 | 3 | js有三种代码会产生上下文。函数,全局变量,eveal。 4 | 5 | 为了管理多个上下文。会有一个上下文栈。每个栈底都是global全局变量。 6 | 7 | 每个上下文包含三个重要的信息。vo、作用域链、this 8 | 9 | vo是变量对象。在创建上下文的时候,生存这个vo对象。这个vo对象。函数的定义、参数等、。当进入到上下文的时候,会转换成AO活动对象。这个AO里面包括argements对象。也是参数。这个对象里面包括参数的格式,以及参数的值。然后扫描内部的变量。填充到ao对象里, 10 | ``` 11 | 12 | AO:{ 13 | argements{ 14 | 15 | }, 16 | vars:'', 17 | fn:"" 18 | } 19 | ``` 20 | 21 | 作用域链。每个函数的作用域链包括当前的函数的AO,以及所有父亲的vo。 22 | 23 | 变量声明不会干扰VO中已经存在的同名函数声明或形式参数声明 -------------------------------------------------------------------------------- /Javascript/Javascript(DOM)/Dom(elment属性).md: -------------------------------------------------------------------------------- 1 | ## node节点属性 2 | 3 | - **attributes** 4 | 5 | 每个节点都有一个attitude属性。这是属性的集合。 6 | 7 | ``` 8 |
9 |
10 | 11 | var app = document.getElmentById('app') 12 | 13 | var attrs = app.attributes // 14 | 15 | attrs[0].name //id 16 | 17 | attrsp[0].value //app 18 | 19 | ``` 20 | 21 | - **节点对象的属性** 22 | 23 | HTML元素的属性名是大小写不敏感的,但是JavaScript对象的属性名是大小写敏感的。转换规则是,转为JavaScript属性名时,一律采用小写。如果属性名包括多个单词,则采用骆驼拼写法,即从第二个单词开始,每个单词的首字母采用大写,比如==onClick== 24 | 25 | ``` 26 | 27 | app.id //app 28 | ``` 29 | 30 | - **节点属性的方法** 31 | 32 | ``` 33 | getAttribute() 34 | setAttribute() 35 | hasAttribute() 36 | removeAttribute() 37 | ``` 38 | 39 | ``` 40 | app.getAttribute('id') //app 41 | 42 | app.setAttribute('class','appClass') 43 | 44 | if(app.hasAttrbite('class')) { 45 | 46 | } 47 | app.removeAttribute('class') 48 | 49 | ``` 50 | 51 | - **dataset ** 52 | 53 | dataset属性解决自定义属性。使用标准提供的data-*属性。 54 | 55 | ``` 56 | app.dataset.user //tian 57 | 58 | ``` -------------------------------------------------------------------------------- /Javascript/Javascript(get和set).md: -------------------------------------------------------------------------------- 1 | ## get 和 set 2 | 3 | get 语法将一个对象属性绑定到查询该属性时将被调用的一个函数上。 4 | 5 | {get prop() { ... } } 6 | 7 | {get [expression]() { ... } } 8 | 9 | 注意事项 10 | 11 | - 可以使用数值或字符串作为标识 12 | - 必须不带参数 13 | - 在对象字面量中,同一个属性不能有两个get,也不能既有get又有属性键值对(不允许使用 { get x() { }, get x() { } } 和 { x: ..., get x() { } } ) 14 | 15 | 16 | var user = { 17 | "first_name":"张", 18 | "second_name":"三", 19 | get fullName(){ 20 | return this.first_name+this.second_name 21 | } 22 | } 23 | console.log(user.fullName) 24 | 25 | ### 使用delete 删除getter 26 | 27 | delete user.fullName; 28 | 29 | 30 | ## setter 31 | 32 | > set 语法将对象属性绑定到要调用的一个函数上, 当尝试设置该属性时 33 | 34 | {set prop(val) { . . . }} 35 | 36 | ### 注意事项 37 | 38 | 1. 它的标识符可以是 number 与 string 二者之一 39 | 2. 必须有一个参数 40 | 3. 不能存在两个set和为一个已经存在的属性设置setter 41 | 42 | 43 | var user = { 44 | "first_name":"张", 45 | "second_name":"三", 46 | get fullName(){ 47 | return this.first_name+this.second_name 48 | }, 49 | set fullName(name){ 50 | this.first_name ="王" 51 | } 52 | } 53 | user.fullName = "11"; 54 | console.log(user.fullName)//王三 -------------------------------------------------------------------------------- /Javascript/Javascript箭头函数.md: -------------------------------------------------------------------------------- 1 | ## js箭头函数 2 | 3 | > 一个箭头函数表达式的语法比一个函数表达式更短,并且不绑定自己的 this,arguments,super或 new.target。 4 | > 箭头函数的引入有两个方面的作用:一是更简短的函数书写,二是对 this的词法解析 5 | 6 | - 当只有一个参数的时候,可以省略圆括号() 7 | 8 | a=>{console.log()} 9 | 10 | - 当删除花括号时,它将是一个隐式的返回值,这意味着我们不需要指定我们返回 11 | 12 | (a)=>a // (a)=>{return a} 13 | 14 | - 如果箭头函数没有参数,必须使用()或者_代替 15 | 16 | _=>{} 17 | ()=>{} 18 | 19 | - 对函数体使用原括号, 返回一个**对象**字面表达式 20 | 21 | a=>({}) 22 | 23 | - 支持 剩余参数 Rest parameters 和默认参数 default parameters: 24 | 25 | (a,b,c=1)=>{console.log(c)} 26 | (a,b,c,...reset)=>{} 27 | 28 | ### 不绑定 this 29 | 30 | > 在箭头函数出现之前,每个新定义的函数都有其自己的 this 值 31 | 32 | 'use strict'; 33 | function Person(){ 34 | this.age = '23'; 35 | var test = ()=>{ 36 | console.log(this.age) 37 | } 38 | test(); 39 | } 40 | var a1 = new Person() //23 41 | 42 | ### 不绑定参数 43 | 44 | > 箭头函数不会在其内部暴露出参数(arguments ): arguments.length, arguments[0], arguments[1] 等等,都不会指向箭头函数的 arguments,而是指向了箭头函数所在作用域的一个名为 arguments 的值(如果有的话,否则,就是 undefined 45 | 46 | 47 | ### 注意事项 48 | 49 | 1. 箭头函数不能用作构造器,和 new 一起用就会抛出错误 50 | 2. 箭头函数没有原型属性 51 | 3. yield 关键字通常不能在箭头函数中使用(除非是嵌套在允许使用的函数内)。因此,箭头函数不能用作生成器。 52 | 4. 箭头函数在参数和箭头之间不能换行哦 53 | 54 | 55 | 56 | js的this 是运行的时候调用的。一个函数作为独立使用指向window 57 | 58 | 箭头函数没有自己的this , 59 | 60 | 61 | 箭头函数不适用的场景。 62 | 63 | 1. 箭头函数作为构造函数时。 64 | 65 | function Person(name){ 66 | this.name = name; 67 | } 68 | 69 | let a = new Person('xiao'); 70 | 71 | a.prototype.test= function(){ 72 | 73 | console.log(this.name) 74 | } 75 | 76 | 2. 使用arguments对象的时候 77 | 3. 交互对象。click对象 78 | 79 | -------------------------------------------------------------------------------- /Javascript/Mysql版本介绍.md: -------------------------------------------------------------------------------- 1 | MySQL根据收费与否,分为**MySQL Community Server**(即社区版)和**MySQL Enterprise Edition**(即商业版)。其中商业版包括MySQL标准版、MySQL企业版、MySQL集群版三个版本 2 | 3 | 4 | 包含以下组件: 5 | 6 | (1)MySQL Database 7 | 8 | (2)MySQL Enterprise Backup 9 | 10 | (3)MySQL Enterprise Monitor 11 | 12 | (4)MySQL Workbench Standard Edition 13 | 14 | 15 | 其它相关工具 16 | 17 | MySQL Cluster MySQL集群 18 | 19 | MySQL Cluster CGE 即MySQL Cluster 20 | 的收费版本,包括: 21 | 22 |   (1)MySQL Cluster 23 | 24 |   (2)MySQL Cluster Manager 25 | 26 |   (3)MySQL Enterprise Backup 27 | 28 |   (4)MySQL Enterprise Monitor 29 | 30 |   (5)MySQL Workbench Standard Edition -------------------------------------------------------------------------------- /Javascript/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tianlei/nodejs", 3 | "authors": [ 4 | { 5 | "name": "xianyun", 6 | "email": "tianlei@qq.com" 7 | } 8 | ], 9 | "require": { 10 | "hprose/hprose": "^2.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Javascript/config: -------------------------------------------------------------------------------- 1 | [core] 2 | repositoryformatversion = 0 3 | filemode = false 4 | bare = false 5 | logallrefupdates = true 6 | symlinks = false 7 | ignorecase = true 8 | [remote "origin"] 9 | url = https://git.oschina.net/xianyunyehe/school.git 10 | fetch = +refs/heads/*:refs/remotes/origin/* 11 | [branch "master"] 12 | remote = origin 13 | merge = refs/heads/master 14 | [branch "dev"] 15 | remote = origin 16 | merge = refs/heads/dev 17 | -------------------------------------------------------------------------------- /Javascript/dva操作.md: -------------------------------------------------------------------------------- 1 | ## dva setup中 需要获取state 2 | 3 | 今天遇到一个需求,就是在setup中,需要获取state的值。但是直接在setup是无法操作的。只是通过dispatch来操作. 4 | 5 | ```js 6 | 7 | export default { 8 | 9 | namespace: 'example', 10 | 11 | state: { 12 | user_id: 1 13 | }, 14 | 15 | subscriptions: { 16 | setup({ dispatch, history }) { // eslint-disable-line 17 | dispatch({type:"test"}) 18 | }, 19 | }, 20 | 21 | effects: { 22 | *fetch({ payload }, { call, put }) { // eslint-disable-line 23 | yield put({ type: 'save' }); 24 | }, 25 | *test({ payload }, { call, put,select }){ 26 | const user_id = yield select(state => state.example.user_id) 27 | } 28 | }, 29 | 30 | reducers: { 31 | save(state, action) { 32 | console.log(action.payload) 33 | return { ...state, ...action.payload }; 34 | }, 35 | }, 36 | 37 | }; 38 | 39 | ``` 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Javascript/ecmascript 6.md: -------------------------------------------------------------------------------- 1 | ## Ecmscript6 2 | 3 | ### let const 4 | ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。 5 | 6 | { 7 | let a =1 8 | } 9 | console.log(a)//undified 10 | 11 | 例子对比 12 | 13 | for(var i =0;i<10;i++){ 14 | 15 | } 16 | console.log(i)//10 17 | 18 | //es6 19 | for(let i =0;i<10;i++){ 20 | console.log(i) 21 | } 22 | console.log(i)//undifiend 23 | 24 | > 不存在变量提升问题 25 | 26 | // var 的情况 27 | console.log(foo); // 输出undefined 28 | var foo = 2; 29 | 30 | // let 的情况 31 | console.log(bar); // 报错ReferenceError 32 | let bar = 2; 33 | 34 | > 不允许重复声明 35 | 36 | var a = 1; 37 | let a =10; 38 | console.log(a)//error 39 | 40 | 41 | ### const命令 42 | 43 | > const声明一个只读的常量。一旦声明,常量的值就不能改变。 44 | 45 | const PI = 3.14; 46 | PI = 34;//TypeError 47 | 48 | ### ES6声明变量的6种方法 49 | 50 | > **var**命令和function命令 let和const命令 import命令和class命令 51 | 52 | ### 顶级对象 53 | 54 | 顶层对象,在浏览器环境指的是window对象,在Node指的是global对象。ES5之中,顶层对象的属性与全局变量是等价的。 55 | 56 | ES6为了改变这一点,一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,**======let命令====、const命令、class命令声明的全局变量==**,不属于顶层对象的属性。也就是说,从ES6开始,全局变量将逐步与顶层对象的属性脱钩。 57 | 58 | var a = "a"; 59 | let b = "b" 60 | console.log(window.a)//a 61 | console.log(window.b)//undifind 62 | 63 | //获取顶级对象 64 | 65 | (typeof window !== 'undefined' 66 | ? window 67 | : (typeof process === 'object' && 68 | typeof require === 'function' && 69 | typeof global === 'object') 70 | ? global 71 | : this); -------------------------------------------------------------------------------- /Javascript/ecmascript6-笔记2.md: -------------------------------------------------------------------------------- 1 | ## 数组解构 2 | 3 | > 数组解析 就是把数组的值赋值给变量 类似于php的list 4 | 5 | let [a,b] = [1,2]; 6 | 7 | console.log(a)//1 8 | console.log(b)//2 9 | 10 | 11 | ## 对象的解构 12 | 13 | let {"a","b"} = {"foo":'1',"tt":"d"} 14 | // 默认值写法 15 | let {a=1} = {} 16 | 17 | ## 字符串的解构 18 | 19 | const [a, b, c, d, e] = 'hello'; 20 | console.log(a) //h 21 | 22 | -------------------------------------------------------------------------------- /Javascript/es6字符串函数.md: -------------------------------------------------------------------------------- 1 | 2 | ## 新增字符串函数 3 | 4 | 5 | startWith(string,postion)// 是不是某个字符开头的 6 | endWith(string,postion) 7 | includes()。 8 | repeat() 9 | 10 | 11 | forEach 不能break 12 | 13 | for in 会把对象的属性也遍历出来。 14 | 15 | for of 可以遍历map 数组。 16 | 17 | 18 | Array.entries(); -------------------------------------------------------------------------------- /Javascript/javascript基本语法笔记/Javascript类型转换.md: -------------------------------------------------------------------------------- 1 | ## 类型转换 2 | 3 | 4 | > 强制转换主要指使用**Number、String**和**Boolean**三个构造函数,手动将各种类型的值,转换成数字、字符串或者布尔值 5 | 6 | 7 | ### Number 8 | 9 | Number函数将字符串转为数值,要比parseInt函数严格很多。基本上,只要有一个字符无法转成数值,整个字符串就会被转为NaN 10 | 11 | ``` 12 | 13 | parseInt('42 cats') // 42 14 | Number('42 cats') // NaN 15 | 16 | //parseInt逐个解析字符,而Number函数整体转换字符串的类型 17 | 18 | Number({a: 1}) // NaN 19 | Number([1, 2, 3]) // NaN 20 | Number([5]) // 5 21 | 22 | ``` 23 | 24 | 1. 调用对象自身的valueOf方法。如果返回原始类型的值,则直接对该值使用Number函数,不再进行后续步骤。 25 | 26 | 2. 如果valueOf方法返回的还是对象,则改为调用对象自身的toString方法。如果toString方法返回原始类型的值,则对该值使用Number函数,不再进行后续步骤。 27 | 28 | 3. 如果toString方法返回的是对象,就报错 29 | 30 | ``` 31 | 32 | var obj = {x: 1}; 33 | Number(obj) // NaN 34 | 35 | // 等同于 36 | if (typeof obj.valueOf() === 'object') { 37 | Number(obj.toString()); 38 | } else { 39 | Number(obj.valueOf()); 40 | } 41 | 42 | ``` 43 | 44 | ### String 45 | 46 | String函数,可以将任意类型的值转化成字符串 47 | 48 | - 数值:转为相应的字符串。 49 | - 字符串:转换后还是原来的值。 50 | - 布尔值:true转为"true",false转为"false"。 51 | - undefined:转为"undefined"。 52 | - null:转为"null" 53 | - 对象 如果是对象,返回一个类型字符串;如果是数组,返回该数组的字符串形式 54 | 55 | ``` 56 | String({a: 1}) // "[object Object]" 57 | String([1, 2, 3]) // "1,2,3" 58 | 59 | ``` 60 | 61 | ### Boolean() 62 | 63 | 除了以下六个值的转换结果为false,其他的值全部为true。 64 | 65 | undefined 66 | null 67 | -0 68 | 0或+0 69 | NaN 70 | ''(空字符串) -------------------------------------------------------------------------------- /Javascript/javascript基本语法笔记/Javascript(数组).md: -------------------------------------------------------------------------------- 1 | ## 数组 2 | 3 | 数组是按次序排列的一组值。每个元素都有自己的序号。 4 | 5 | 本质上,数组属于一种特殊的对象。typeof运算符会返回数组的类型是object。 6 | 7 | 8 | 9 | ``` 10 | var arr = [1,2,3] 11 | 12 | typeof arr === 'object' //true 13 | 14 | Object.keys(arr) //获取所有的键名 15 | 16 | 17 | ``` 18 | 19 | ### length 属性 20 | 21 | length属性表示数组的成员数量。JavaScript使用一个32位整数,保存数组的元素个数。这意味着,数组成员最多只有4294967295个(232 - 1)个,也就是说length属性的最大值就是4294967295 22 | 23 | length等于键名中最大数加1 因为从0 开始 24 | 25 | ``` 26 | var arr = [1,2] 27 | 28 | arr[10] =4 29 | 30 | arr.length // 11 而不是3 31 | 32 | ``` 33 | 34 | length属性是可写的。如果人为设置一个小于当前成员个数的值,该数组的成员会自动减少到length设置的值。 35 | 36 | 37 | ``` 38 | arr.length = 1 39 | 40 | //那么2将不在该数组中了 41 | 42 | arr.length = 0 //清空数组 43 | 44 | ``` 45 | 46 | 将数组的键分别设为字符串和小数,结果都不影响length属性。因为,length属性的值就是等于最大的数字键加1 47 | 48 | ``` 49 | var arr =[] 50 | arr['a'] = 10 51 | arr.length //0 52 | 53 | ``` 54 | 55 | ### 类似数组的对象 56 | 57 | 有些对象被称为“类似数组的对象”(array-like object)。意思是,它们看上去很像数组,可以使用length属性 58 | 59 | ``` 60 | 61 | var obj = { 62 | 0:"a", 63 | 1:"b" 64 | c:"c" 65 | } 66 | 67 | obj.length 68 | 69 | ``` 70 | 71 | ### 数组的空位 72 | 73 | 数组的某个位置是空元素,即两个逗号之间没有任何值,我们称该数组存在空位 74 | 如果最后一个元素后面有逗号,并不会产生空位。也就是说,有没有这个逗号,结果都是一样的 75 | 76 | ``` 77 | var a = [1, , 1]; 78 | a.length // 3 79 | 80 | var b= [1,2,3,] 81 | b.length //3 82 | 83 | ``` 84 | 85 | ### 数组的遍历 86 | 87 | 88 | ``` 89 | 90 | var arr = [1,2,3] 91 | 92 | arr.forEach(function(v){ 93 | console.log(v) 94 | }) 95 | 96 | 97 | for (var i =0;i javascript 共有6种数据类型。 4 | 5 | 1. 数值 包括整型和浮点型 6 | 2. 字符串 7 | 3. null 8 | 4. undefined 9 | 5. 对象 10 | 6. 布尔类型 11 | 12 | 其中对象可以细分为数组,函数,object 13 | 14 | ### 类型判断 15 | 16 | 1. typeof 17 | 2. instanceof 18 | 3. Object.prototype.toString 19 | 20 | typeof 21 | 22 | - 对于数值返回number 23 | 24 | - 对于字符串返回string 25 | - 对于函数 -------------------------------------------------------------------------------- /Javascript/js深拷贝和浅拷贝.md: -------------------------------------------------------------------------------- 1 | ## 深拷贝和浅拷贝 2 | 在js中,我们经常会听到深拷贝和浅拷贝,自己也是一头雾水,查阅资料发现,原来就是一个指针的意思 3 | 4 | ### 浅拷贝 5 | 6 | 浅拷贝的意思就是放一个变量进行赋值给另外一个值的时候,两个值的地址是一样,改变一个值的时候,两外一个也会随着改变。 类似php的& 7 | 8 | ```php 9 | $a = 1; 10 | $b = &a; 11 | 12 | $b =3; //$a=3 13 | 14 | ``` 15 | 16 | ```javascript 17 | let object1 = { 18 | user: "xian", 19 | age: 12 20 | } 21 | 22 | let object2 = object1;//浅拷贝。 23 | 24 | object2.age = 25; 25 | 26 | console.log("object1.age",object1.age);//25 27 | //object2 我们只是复制了一个变量, 但是这个变量却跟之前的指向同一个地址空间,产生了非预期效果。 28 | ``` 29 | 30 | ### 深拷贝 31 | 32 | 深拷贝就是我们其他编程语言中的,值拷贝,地址空间会发生变量 33 | 34 | ```javascript 35 | let object1 = { 36 | user:"xian", 37 | age:12 38 | } 39 | 40 | let object2 = Object.assign({},object1); 41 | 42 | object2.age = 24; 43 | 44 | console.log('object1.age',object1.age);//12 45 | 46 | ``` 47 | ### es6 对象展开符 48 | es6中增加了一个很方便的操作运算符,方便我们进行深拷贝 49 | 50 | ```javascript 51 | let object1 = { 52 | user:"xian", 53 | age:12 54 | } 55 | 56 | let object2 = {...object1} 57 | 58 | object2.age = 24 59 | 60 | console.log(object1.age) 61 | 62 | ``` 63 | 对象合并 64 | 65 | ```javascript 66 | let a = { 67 | 'u':1, 68 | 'b':2 69 | } 70 | let b = { 71 | 'd':3 72 | } 73 | 74 | let c = {...a,...b} 75 | 76 | console.log(c) 77 | ``` 78 | ### 注意事项 79 | 80 | 使用展开符可能使用会出现我们预想不到的结果,对象属性的值的值还是引用.这就是一个副作用的例子 81 | 82 | ```javascript 83 | 84 | const k = {a:[1,2,3,4]} 85 | 86 | const t = {...k} 87 | 88 | t.a[0] = 9 89 | 90 | console.log(k) 91 | 92 | ``` 93 | 94 | ### 参考链接 95 | - [http://lucybain.com/blog/2018/js-es6-spread-operator/](http://lucybain.com/blog/2018/js-es6-spread-operator/) -------------------------------------------------------------------------------- /Javascript/vue/Vue cli3配置proxy.md: -------------------------------------------------------------------------------- 1 | ## Vue cli3 proxy 2 | 在前端的开发过程中,有时候需要进行调后端的接口,但是我们经常会遇到一个跨域的问题。在开发的过程中。可以通过proxy。来实现跨域。 3 | 在vue cli3 中实现可以在配置中。加下以下设置 4 | 5 | ```js 6 | module.exports = { 7 | devServer: { 8 | proxy: { 9 | '/api': { 10 | target: 'https://api.somewhere.com', # 测试环境接口地址 11 | secure: true, 12 | pathRewrite: { 13 | '^/api': '', 14 | }, 15 | } 16 | }, 17 | }, 18 | } 19 | 20 | ``` 21 | 然后在我们的接口请求中,以`axios`为例 只需要把 `baseURL` 改成本地的`/api` 即可 22 | 23 | `/user` 则会转发到`https://api.somewhere.com/user` 24 | ```js 25 | axios.get('/api/user') 26 | ``` 27 | -------------------------------------------------------------------------------- /Javascript/vue/Vue-router-linker.md: -------------------------------------------------------------------------------- 1 | 2 | ## 3 | 4 | > 组件支持用户在具有路由功能的应用中(点击)导航。 通过 to 属性指定目标地址,默认渲染成带有正确链接的 标签,可以通过配置 tag 属性生成别的标签.。另外,当目标路由成功激活时,链接元素自动设置一个表示激活的 CSS 类名。 5 | 6 | ### props 7 | 8 | 9 | - to 10 | 11 | 表示目标路由的链接。当被点击后,内部会立刻把 to 的值传到 router.push() 12 | 13 | 14 | 15 | 16 | - replace 17 | 18 | 设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(),于是导航后不会留下 history 记录。 19 | 20 | - append 21 | 22 | 设置 append 属性后,则在当前(相对)路径前添加基路径 23 | 24 | 25 | 26 | - tag 27 | 28 | 将router-linker渲染成各种指定的标签 默认a 29 | 30 | 路由tag 31 | 32 | 33 | ## router-view 34 | 35 | > 组件是一个 functional 组件,渲染路径匹配到的视图组件。 渲染的组件还可以内嵌自己的 ,根据嵌套路径,渲染嵌套组件。 36 | 37 | ### 属性 38 | 39 | 40 | - name 41 | 42 | 如果 设置了名称,则会渲染对应的路由配置中 components 下的相应组件。查看 命名视图 中的例子。 -------------------------------------------------------------------------------- /Javascript/vue/Vue-router(构造和信息对象).md: -------------------------------------------------------------------------------- 1 | 2 | ## vue-router构造 3 | 4 | - routes 5 | 6 | 7 | - mode 8 | 9 | 类型: string 10 | 11 | 默认值: "hash" (浏览器环境) | "abstract" (Node.js 环境) 12 | 13 | 可选值: "hash" | "history" | "abstract" 14 | 15 | 配置路由模式: 16 | 17 | - hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器。 18 | 19 | - history: 依赖 HTML5 History API 和服务器配置。查看 HTML5 History 模式. 20 | 21 | - abstract: 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式。 22 | 23 | - base 24 | 25 | 类型: string 26 | 27 | 默认值: "/" 28 | 29 | 应用的基路径。例如,如果整个单页应用服务在 /app/ 下,然后 base 就应该设为 "/app/" 30 | 31 | 32 | - linkActiveClass 33 | 34 | 全局配置 的默认『激活 class 类名 35 | 36 | 37 | - scrollBehavior 38 | 39 | function 40 | 41 | scrollBehavior(to, from, savedPosition){} 42 | 43 | 44 | const router = new VueRouter({ 45 | base:"/app/", 46 | linkActiveClass:"actice", 47 | mode:"history", 48 | routes:[ 49 | {}, 50 | {} 51 | ] 52 | }) 53 | 54 | ## 路由信息对象 55 | 56 | 57 | > 一个 route object(路由信息对象) 表示当前激活的路由的状态信息,包含了当前 URL 解析得到的信息,还有 URL 匹配到的 route records(路由记录) 58 | 59 | ### 路由信息对象的属性 60 | 61 | - name 62 | 63 | 如果有则是命名路由的名字 64 | 65 | - fullPath 66 | 67 | 路由的完整匹配路径 68 | 69 | - params 70 | 71 | 路由的参数 72 | 73 | - query 74 | 75 | 路由的查询的query 生成/user?id=100 76 | 77 | query -------------------------------------------------------------------------------- /Javascript/vue/Vuex介绍.md: -------------------------------------------------------------------------------- 1 | ## Vuex 2 | 3 | > Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化 4 | 5 | 6 | >Vuex 使用 单一状态树 —— 是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个『唯一数据源(SSOT)』而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照 -------------------------------------------------------------------------------- /Javascript/vue/Vue插件.md: -------------------------------------------------------------------------------- 1 | ## vue插件 2 | 3 | 4 | 插件通常会为Vue添加全局功能。插件的范围没有限制——一般有下面几种: 5 | 6 | 1. 添加全局方法或者属性,如: vue-element 7 | 1. 添加全局资源:指令/过滤器/过渡等,如 vue-touch 8 | 1. 通过全局 mixin方法添加一些组件选项,如: vuex 9 | 1. 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。 10 | 1. 一个库,提供自己的 API,同时提供上面提到的一个或多个功能,如 vue-router 11 | 12 | Vue.js 的插件应当有一个公开方法 install 。这个方法的第一个参数是 Vue 构造器 , 第二个参数是一个可选的选项对象: 13 | 14 | 15 | MyPlugin.install = function (Vue, options) { 16 | // 1. 添加全局方法或属性 17 | Vue.myGlobalMethod = function () { 18 | // 逻辑... 19 | } 20 | // 2. 添加全局资源 21 | Vue.directive('my-directive', { 22 | bind (el, binding, vnode, oldVnode) { 23 | // 逻辑... 24 | } 25 | ... 26 | }) 27 | // 3. 注入组件 28 | Vue.mixin({ 29 | created: function () { 30 | // 逻辑... 31 | } 32 | ... 33 | }) 34 | // 4. 添加实例方法 35 | Vue.prototype.$myMethod = function (options) { 36 | // 逻辑... 37 | } 38 | } -------------------------------------------------------------------------------- /Javascript/vue/vue(x-template和inline-template)模板.md: -------------------------------------------------------------------------------- 1 | ## x-template 2 | 3 | 一种定义模版的方式是在 JavaScript 标签里使用 text/x-template 类型,并且指定一个id 4 | 5 | 8 | 9 | var vm = new Vue({ 10 | components:{ 11 | "test":{ 12 | "template":"#test" 13 | } 14 | } 15 | }) 16 | 17 | 18 | ## inline-template 19 | 20 | > 如果子组件有 inline-template 特性,组件将把它的内容当作它的模板,而不是把它当作分发内容。这让模板更灵活 21 | 22 | 23 |
    24 |
  • 11
  • 25 |
  • 33
  • 26 |
27 |
28 | 29 | let vm = new Vue({ 30 | el:"#app", 31 | data:{ 32 | 33 | }, 34 | components:{ 35 | "inline":{ 36 | "template":"
" 37 | } 38 | } 39 | 40 | 41 | }) -------------------------------------------------------------------------------- /Javascript/vue/vue-slots.md: -------------------------------------------------------------------------------- 1 | ## 匿名插槽 2 | 3 | ```vue 4 | //child.vue 5 | 10 | 11 | // farther 12 | 13 | 19 | 20 | ``` 21 | 22 | ## 具名插槽 23 | 24 | ```vue 25 | 33 | 34 | 35 | 39 | ``` 40 | 41 | ## 插槽传值 42 | 43 | ```vue 44 | 50 | 51 | 52 | 57 | ``` 58 | -------------------------------------------------------------------------------- /Javascript/vue/vue3.provide.md: -------------------------------------------------------------------------------- 1 | ## Provide / Inject 2 | 3 | 当我们通过父组件向子组件传递数据,可以通过`props` 但是如果我们向子组件的下级的下级传递,如果通过props一层层的传递,非常麻烦。我们可以通过`provide`进行包裹 4 | 5 | 这样父节点下面的所有节点就能拿到对应的数据。 6 | 7 | ```vue 8 | // parent 9 | 24 | // son 25 | 26 | 27 | 39 | ``` 40 | 41 | -------------------------------------------------------------------------------- /Javascript/vue/vue混合.md: -------------------------------------------------------------------------------- 1 | ## vue混合 2 | 3 | 混合是一种灵活的分布式复用 Vue 组件的方式。混合对象可以包含任意组件选项。以组件使用混合对象时,所有混合对象的选项将被混入该组件本身的选项。 4 | 5 | 6 | let mix = { 7 | created:function(){ 8 | console.log('create') 9 | } 10 | } 11 | let component = Vue.extend({ 12 | mixins:[mix] 13 | }) 14 | let vm = new component() 15 | 16 | let vm2 = new Vue({ 17 | mixins:[ 18 | { 19 | "created":function () { 20 | console.log('test') 21 | } 22 | } 23 | ] 24 | }) 25 | 26 | 27 | > 值为对象的选项,例如 methods, components 和 directives,将被混合为同一个对象。 两个对象键名冲突时,取组件对象的键值对。 -------------------------------------------------------------------------------- /Javascript/vue/vue过渡.md: -------------------------------------------------------------------------------- 1 | ## Vue过渡效果 2 | 3 | Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加 entering/leaving 过渡 4 | 条件渲染 (使用 v-if) 5 | 条件展示 (使用 v-show) 6 | 动态组件 7 | 组件根节点 8 | 9 | 10 | ### 过渡的-CSS-类名 11 | 12 | 会有 4 个(CSS)类名在 enter/leave 的过渡中切换 13 | v-enter: 定义进入过渡的开始状态。在元素被插入时生效,在下一个帧移除。 14 | v-enter-active: 定义进入过渡的结束状态。在元素被插入时生效,在 transition/animation 完成之后移除。 15 | v-leave: 定义离开过渡的开始状态。在离开过渡被触发时生效,在下一个帧移除。 16 | v-leave-active: 定义离开过渡的结束状态。在离开过渡被触发时生效,在 transition/animation 完成之后移除。 17 | 18 | v- 是这些类名的前缀 19 | 20 | 21 | ### 自定义过渡类名 22 | 23 | 我们可以通过以下特性来自定义过渡类名: 24 | 25 | - enter-class 26 | - enter-active-class 27 | - leave-class 28 | - leave-active-class 29 | - 30 | 31 | ### 过渡的钩子 32 | 33 | 34 | - v-on:before-enter="beforeEnter" 35 | - v-on:enter="enter" 36 | - v-on:after-enter="afterEnter" 37 | - v-on:enter-cancelled="enterCancelled" 38 | - v-on:before-leave="beforeLeave" 39 | - v-on:leave="leave" 40 | - v-on:after-leave="afterLeave" 41 | - v-on:leave-cancelled="leaveCancelled" 42 | - 43 | 44 | > 推荐对于仅使用 JavaScript 过渡的元素添加 v-bind:css="false",Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。 45 | 46 | 47 | ### 初始化过渡 48 | 49 | 50 | 可以通过 appear 特性设置节点的在初始渲染的过渡 51 | 52 | 53 | ## 列表过渡 54 | 55 | > 56 | 不同于 , 1.它会以一个真实元素呈现:默认为一个 。你也可以通过 tag 特性更换为其他元素。 57 | 内部元素 总是需要 提供唯一的 key 属性值 58 | 59 | ### 列表的偏移 60 | 61 | > 组件还有一个特殊之处。不仅可以进入和离开动画,还可以改变定位。要使用这个新功能只需了解新增的 v-move 特性,它会在元素的改变定位的过程中应用。像之前的类名一样,可以通过 name 属性来自定义前缀,也可以通过 move-class 属性手动设置。 -------------------------------------------------------------------------------- /Javascript/w_h.md: -------------------------------------------------------------------------------- 1 | ## JavaScript获取页面的各种宽度和高度 2 | - window.screen.width| window.screen.height 获取屏幕的宽高 3 | - window.innerWidth| window.innerHeight 浏览器视口(viewport)的宽和高,包括滚动条长度 4 | - window.outWidth | window.outHeight 浏览器窗口的宽和高,包含侧边栏、边框 5 | 6 | ## 获取element的宽度和高度 7 | - ELE.clientWidth | ELE.clientHeight css的height+css的padding 8 | - ELE.scrollWidth | ELE.scrollHeight 适应视口中所用内容所需的最小高度/宽度 9 | - ELE.getBoundingClientRect() 获取dom元素距离视口的位置 10 | -------------------------------------------------------------------------------- /Javascript/对象解构.md: -------------------------------------------------------------------------------- 1 | ## 对象解构 2 | 3 | const user = { 4 | name:"", 5 | age:"", 6 | height:"" 7 | } 8 | 9 | //重新命名 name:n birthday 是unfined 默认值 10 | const {name:n,age,birthday = ''} = user 11 | console.log(name) 12 | console.log(age) 13 | 14 | 快速解构对象。如果对象中没有可以给一个默认值 15 | 16 | -------------------------------------------------------------------------------- /Javascript/模板字符串.md: -------------------------------------------------------------------------------- 1 | ## 模板字符串 2 | 3 | 使用反引号 \`\` 在字符里可以使用${variable} 引用对象 4 | 5 | let name = "xiao" 6 | const templatet = ` 7 |
${name}
8 | ` 9 | 10 | ## 标签字符串 11 | 12 | 13 | function lower(string, ...value){ 14 | 15 | return value; 16 | } 17 | let item = 111 18 | const template = lower`
${item}
` 19 | 20 | 21 | array.reduce(function(pre,current,i){ 22 | 23 | }) -------------------------------------------------------------------------------- /Laravel/Cache.md: -------------------------------------------------------------------------------- 1 | ## Laravel 缓存 2 | 3 | > Laravel 给各种不同的缓存系统提供了统一的 API,缓存的配置文件都放在 config/cache.php 中,在这个文件中,你可以指定默认想用哪个缓存驱动,Laravel 支持当前流行的缓存后端 4 | 5 | - 数据库缓存 6 | 7 | > 使用数据库作为缓存 需要设置一个缓存的表 8 | 9 | 10 | Schema::create('cache', function($table) { 11 | $table->string('key')->unique(); 12 | $table->text('value'); 13 | $table->integer('expiration'); 14 | }); 15 | 16 | php artisan cache:table 17 | 18 | - Memcached缓存 19 | 20 | > 使用 Memcached 做缓存需要先安装 Memcached PECL 扩展包。 21 | 22 | 'memcached' => [ 23 | [ 24 | 'host' => '127.0.0.1', 25 | 'port' => 11211, 26 | 'weight' => 100 27 | ], 28 | ], 29 | 30 | 'memcached' => [ 31 | [ 32 | 'host' => '/var/run/memcached/memcached.sock', 33 | 'port' => 0, 34 | 'weight' => 100 35 | ], 36 | ], 37 | 38 | 39 | - redis 40 | 41 | > 使用 Redis 之前,你必须通过 Composer 安装 predis/predis 扩展包(~1.0)。 42 | 43 | composer require "predis/predis:~1.0" 44 | 45 | 配置 46 | 47 | 'redis' => [ 48 | 'cluster' => false, 49 | 'default' => [ 50 | 'host' => '127.0.0.1', 51 | 'port' => 6379, 52 | 'database' => 0, 53 | ], 54 | 55 | ], 56 | 57 | 58 | ### 缓存的使用 59 | 60 | 61 | 使用cache的facade 62 | 63 | - 读取缓存 64 | 65 | Cache::get(key); 66 | Cache::get(key,default) 67 | 68 | - 判断值是否存在 69 | 70 | Cache::has(key) 71 | 72 | - 写入缓存 73 | 74 | Cache::put(key,val,expires) 75 | Cache::forever('key', 'value');//永久的cache 76 | 77 | - 删除缓存 78 | 79 | Cache::flush();//清空缓存 80 | 81 | Cache::forget(key) //移除一个缓存值 82 | 83 | - -------------------------------------------------------------------------------- /Laravel/Config.md: -------------------------------------------------------------------------------- 1 | ## Laravel Config的使用 2 | 3 | > 配置文件存放在app\config目录下, 4 | 5 | 6 | use Illuminate\Support\Facades\Config; 7 | 8 | 9 | Config::get('app.timezone') //读取配置 app.php下的timezone的信息 10 | 11 | Config::set('app.timezone','PRC');//设置 -------------------------------------------------------------------------------- /Laravel/Controller.md: -------------------------------------------------------------------------------- 1 | ## Laravel控制器 2 | 3 | App\Http\Controllers\Controller; 4 | 5 | class DemoController extends Controller{} 6 | 7 | 8 | ### 控制器中间件 9 | 10 | Route::get('profile', [ 11 | 'middleware' => 'auth', 12 | 'uses' => 'UserController@showProfile' 13 | ]); 14 | 15 | ### RESTful 资源控制器 16 | 17 | 资源控制器让你可以轻松地创建与资源相关的 RESTful 控制器 18 | 19 | - 创建一个资源控制器 20 | 21 | php artisan make:controller PhotoController --resource 22 | 23 | 24 | 动词介绍 25 | 26 | > 动词 路径 行为(方法) 路由名称 27 | GET /photo index photo.index 28 | GET /photo/create create photo.create 29 | POST /photo store photo.store 30 | GET /photo/{photo} show photo.show 31 | GET /photo/{photo}/edit edit photo.edit 32 | PUT/PATCH /photo/{photo} update photo.update 33 | DELETE /photo/{photo} destroy photo.destroy 34 | 35 | 36 | ### 依赖注入与控制器 37 | 38 | > 依赖注入就是 通过构造 将类导入到当前控制器中 39 | 40 | public function __construct(UserRepository $users) 41 | { 42 | $this->users = $users; 43 | } 44 | 45 | ### 路由缓存 46 | 47 | > 路由缓存并不会作用在基于闭包的路由。要使用路由缓存,你必须将所有闭包路由转换为控制器类 48 | 49 | php artisan route:cache 50 | 51 | 清除路由缓存 52 | 53 | php artisan route:clear -------------------------------------------------------------------------------- /Laravel/Email.md: -------------------------------------------------------------------------------- 1 | ## 邮件发送 2 | 3 | ### 1. 配置驱动 4 | 5 | ```php 6 | 'driver' => env('MAIL_DRIVER', 'smtp'), 7 | ``` 8 | 9 | ### 2. 生成右键 10 | 11 | 在 Laravel 中,每种类型的邮件都代表一个「Mailable」对象。这些对象存储在 `app/Mail` 目录中 12 | 13 | ```php 14 | php artisan make:mail UserRegister 15 | ``` 16 | 17 | ### 3. 编写邮件 18 | 19 | 所有的 「Mailable」类都在其 `build` 方法中完成配置。在这个方法里,你可以调用其他各种方法,如 `from` 、 `subject` 、 `view` 和 `attach` 来配置完成邮件的详情 20 | 21 | #### 3.1 配置发送者 22 | 23 | ```php 24 | //配置主题 25 | public $subject = "这是一个测试邮件"; 26 | 27 | //配置from 28 | public $from = [ 29 | [ "name"=>"闲云野鹤", 30 | "address"=>"guohaijiang2000@126.com"] 31 | ]; 32 | 33 | public function build() 34 | { 35 | return $this->from('example@example.com') 36 | ->view('emails.orders.shipped'); 37 | } 38 | ``` 39 | 40 | 41 | 42 | ### 4. 发送邮件 43 | 44 | 要发送邮件,使用 `Mail` [facade](https://laravel-china.org/docs/laravel/5.6/facades) 的 `to` 方法。 `to` 方法接受一个邮件地址,一个 user 实现或一个 users 集合。如果传递一个对象或集合,mailer 将自动使用 `email` 和 `name` 属性来设置邮件收件人,所以确保你的对象里有这些属性。一旦指定收件人,你可以传递一个实现到 Mailable 类的 `send` 方法: 45 | 46 | ```php 47 | Mail::to($request->user())->send(new OrderShipped($order)); 48 | ``` 49 | 50 | -------------------------------------------------------------------------------- /Laravel/Laravel[修改AJAX请求中的422].md: -------------------------------------------------------------------------------- 1 | ## laravel5.4通过ajax提交表单获取到422返回,ajax无法捕获返回内容 2 | 3 | 可以自定义failedValidation来解决 4 | 5 | ```php 6 | json(..., 422)); 22 | } 23 | 24 | } 25 | 26 | 27 | ``` 28 | 29 | 30 | 31 | 参考资料 32 | 33 | - [https://laracasts.com/discuss/channels/laravel/how-make-a-custom-formrequest-error-response-in-laravel-55?page=1](https://laracasts.com/discuss/channels/laravel/how-make-a-custom-formrequest-error-response-in-laravel-55?page=1) 34 | 35 | -------------------------------------------------------------------------------- /Laravel/LifeCycle.md: -------------------------------------------------------------------------------- 1 | ## Laravel的生命周期 2 | 3 | **入口文件** 4 | public/index.php 这个文件是 Laravel 应用程序所有请求的进入点 5 | 6 | **HTTP核心 ** 7 | 应用程序的请求的会被送往 HTTP 核心或终端核心 8 | app/Http/Kernel.php 9 | 10 | HTTP 核心也定义了一份 HTTP 中间件 清单,所有的请求在被应用程序处理之前都必须经过它们。这些中间件处理 HTTP session 的读写、验证 CSRF 令牌、决定应用程序是否处于维护模式,以及其它更多任务作 11 | 12 | **服务提供者** 13 | 14 | 最重要的核心启动加载行为之一,是加载你的应用程序的 服务提供者。应用程序的所有服务提供者,都在 config/app.php 此配置文件的 providers 数组中被设置。首先,所有提供者的 register 方法会被调用,一旦所有提供者都被注册之后,boot 方法就会被调用。 15 | 16 | **请求分派** 17 | 18 | 一旦应用程序被启动且所有的服务提供者都被注册之后,Request 将被移转给路由器进行分派。路由器会将请求分派给路由或控制器,并运行所有特定路由的中间件。 19 | 20 | 21 | ## 程序结构介绍 -------------------------------------------------------------------------------- /Laravel/Middleware.md: -------------------------------------------------------------------------------- 1 | ## Laravel Middleware 2 | 3 | 4 | HTTP 中间件提供了一个方便的机制来过滤进入应用程序的 HTTP 请求 Laravel 框架已经内置了一些中间件,包括维护、身份验证、CSRF 保护,等等 5 | 6 | ### 全局中间件 7 | 8 | 若是希望每个 HTTP 请求都经过一个中间件,只要将中间件的类加入到 app/Http/Kernel.php 的 $middleware 属性清单列表中。 9 | 10 | ###路由指派中间件 11 | 12 | - 创建一个中间件 13 | 14 | php artisan make:middleware MyMiddleware 15 | 16 | - 注册中间件 17 | 18 | protected $routeMiddleware = [ 19 | 20 | 'my'=>\App\Http\Middleware\MyMiddleware::class, 21 | ]; 22 | 23 | - 在路由上使用中间件 24 | 25 | Route::get('my','DemoController@getHome')->middleware('my'); 26 | 27 | - 中间件组 28 | 29 | 通过指定键名的方式来将相关的中间件分配到一个组里面去。 30 | 31 | protected $middlewareGroups = [ 32 | 'web' => [ 33 | \App\Http\Middleware\EncryptCookies::class, 34 | \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, 35 | \Illuminate\Session\Middleware\StartSession::class, 36 | \Illuminate\View\Middleware\ShareErrorsFromSession::class, 37 | \App\Http\Middleware\VerifyCsrfToken::class, 38 | ], 39 | 40 | Route::group(['middleware' => ['web']], function () { 41 | // 42 | }); 43 | 44 | 45 | ### 中间件参数 46 | 47 | public function handle($request, Closure $next,$role) 48 | { 49 | echo $role; 50 | return $next($request); 51 | } 52 | 53 | //中间件参数的路由 54 | Route::get('rule/{id}','DemoController@getHome')->middleware('rule:test'); 55 | 56 | 57 | ### Terminable 中间件 58 | 59 | 在http响应之后执行中间件的内容 60 | Laravel 内置的「session」中间件存储的 session 数据是在响应被发送到浏览器之后才进行写入的。想要做到这一点,你需要定义中间件为「terminable」 -------------------------------------------------------------------------------- /Laravel/Notifications.md: -------------------------------------------------------------------------------- 1 | ## Notifications 2 | 3 | laravel的notifications。用途主要用于发送消息通知。比如短信,邮件等。这个和任务类似。 4 | 5 | ### 1. 创建一个通知 6 | 7 | ```bash 8 | php artisan make:notification InvoicePaid 9 | ``` 10 | 11 | 一个通知,就是一个类,这个类就是处理通知的业务。 12 | 13 | ### 2. 发送通知 14 | 15 | 发送通知可以使用`Notifiable` trait的`notify` 16 | 17 | ```php 18 | use Notifiable; 19 | 20 | public function test() 21 | { 22 | $this->notify(new InvoicePaid($invoice)); 23 | } 24 | ``` 25 | 26 | 使用facade `Notification` 27 | 28 | ```php 29 | Notification::send($users, new InvoicePaid($invoice)); 30 | ``` 31 | 32 | ### 3. 邮件通知 33 | 34 | 一个通知支持邮件通知,应该定义一个`toMail`方法。这个方法接受$Notifiable。 35 | 36 | ```php 37 | public function toMail($notifiable) 38 | { 39 | $url = url('/invoice/'.$this->invoice->id); 40 | 41 | return (new MailMessage) 42 | ->greeting('Hello!') 43 | ->line('One of your invoices has been paid!') 44 | ->action('View Invoice', $url) 45 | ->line('Thank you for using our application!'); 46 | } 47 | ``` 48 | 49 | 50 | 51 | 52 | 53 | ​ -------------------------------------------------------------------------------- /Laravel/Queue.md: -------------------------------------------------------------------------------- 1 | ## 队列 2 | 3 | 当有一些比较费时的操作,我们就可以放到队列里面去处理。Laravel 队列为不同的队列后台服务提供了统一的 API 4 | 5 | 在`config/queue.php`配置对应的drive 6 | 7 | ### 1 .创建job 8 | 9 | 一个job 是一个任务,就是队列中需要执行的任务。 10 | 11 | ```bash 12 | php artisan make:job Process 13 | ``` 14 | 15 | ### 2.编写任务类 16 | 17 | 任务类中handle就是要执行的任务。比如发送短信。导出数据等。 18 | 19 | ```php 20 | /** 21 | * 运行任务。 22 | * 23 | * @param AudioProcessor $processor 24 | * @return void 25 | */ 26 | public function handle(Process $processor) 27 | { 28 | // Process uploaded podcast... 29 | } 30 | ``` 31 | 32 | ### 3.分发任务 33 | 34 | 就是把任务加入队列中 35 | 36 | ```php 37 | Process::dispatch($podcast); 38 | ->onQueue('queue') //指定队列名字 39 | ``` 40 | 41 | -------------------------------------------------------------------------------- /Laravel/Request.md: -------------------------------------------------------------------------------- 1 | ## Request 2 | 3 | ### 获取请求信息 ### 4 | 5 | 通过依赖注入容器来获取请求的信息。 6 | 7 | public function Test( Request $request) 8 | { 9 | 10 | } 11 | 12 | 获取数据 13 | 14 | $request->get('id'); 15 | $request->post('id'); 16 | 17 | 获取请求的地址 18 | 19 | $request->url(); 20 | $request->fullUrl(); 21 | 22 | 获取请求的方法 23 | 24 | $request->method() 25 | 26 | 判断请求方式 27 | 28 | if($request->isMethod('post')) 29 | 30 | ### 旧输入数据 31 | 32 | Laravel 可以让你将本次的输入数据保留到下一次请求发送前 33 | 34 | 闪存到session中 35 | 36 | $request->flash(); 37 | 38 | $request->flashOnly('username', 'email'); 39 | 40 | $request->flashExcept('password'); 41 | 42 | 43 | ### 获取旧的数据 44 | 45 | Laravel 也提供了全局辅助函数 old。如果你要在 Blade 模板 中显示旧输入数据,可以使用更加方便的 old 辅助函数: 46 | 47 | $username = $request->old('username'); 48 | 49 | 50 | ### cookie 数据 51 | 52 | 53 | $request->cookie('cookie1'); 54 | 55 | ### 文件上传 56 | 57 | $request->file('name');//获取上传的文件信息 58 | $request->hasFile('name') 判断是否上传 59 | $request->file('photo')->isValid() //判断文件是否有效 60 | $request->file('photo')->move('./tests','aa.jpg');//移动到目标位置 -------------------------------------------------------------------------------- /Laravel/Route.md: -------------------------------------------------------------------------------- 1 | ## Laravel 路由的使用 2 | 3 | 4 | > Laravel的路由默认存放在routes.php 5 | 6 | 7 | - 简单 8 | 9 | Route::get('/',function(){ 10 | return view('welcome'); 11 | }) 12 | Route::get('/test',ControllerName@function); 13 | 14 | - 控制器路由 15 | 16 | Route::Controller('/test','TestController'); 17 | /test/index = 18 | TestController/getIndex 19 | 20 | - Restful资源路由 21 | 22 | Route::resource('posts','PostsController') 23 | Route::resource('phote','PhotoController',['only'=>'index']);//只允许index动作 24 | 25 | - HTTP请求方式路由 26 | 27 | Route::any('aa',function(){});//允许任何 28 | Route::post('aa',function(){});//post 29 | 30 | - 安全路由 31 | 32 | Route::get('b',['https',function(){ 33 | echo "allow https"; 34 | }]) 35 | 36 | - 路由约束 37 | 38 | Route::get('test/{bar}','DemoController@getIndex')->where('bar','[0-9]+'); 39 | 40 | - http 中间件 41 | 42 | Route::get('test1',['middleware'=>'Test',function(){ 43 | return 1; 44 | }]); 45 | 46 | 47 | - 命名路由 48 | 49 | Route::get('fo/test',['as'=>'fotest',function(){ 50 | echo route('fotest'); 51 | }]); //使用route 函数生成 52 | 53 | Route::get('user/test','DemoController@getIndex')->name('test2'); 54 | 55 | - 路由前缀 56 | 57 | Route::group(['prefix'=>'admin'],function(){ 58 | Route::get('users','DemoController@getIndex'); 59 | }); //admin/users 60 | 61 | - 子域名路由 62 | 63 | Route::group([ 64 | 'domain'=>'{sub.aa.com}',function(){ 65 | 66 | } 67 | ]); -------------------------------------------------------------------------------- /Laravel/Validation.md: -------------------------------------------------------------------------------- 1 | ## Laravel 表单验证 2 | 3 | ### 1. 创建表单验证 4 | 5 | ```shell 6 | php artisan make:request PostRequest 7 | ``` 8 | 9 | ### 2. 添加验证规则 10 | 11 | ```php 12 | class PostRequest extends FormRequest 13 | { 14 | public function rules() 15 | { 16 | return [ 17 | 'username' => 'required|max:255', 18 | 'password' => 'required', 19 | ]; 20 | } 21 | 22 | /** 23 | * 获取已定义的验证规则的错误消息。 24 | * 25 | * @return array 26 | */ 27 | public function messages() 28 | { 29 | return [ 30 | 'username.required' => '用户名不能为空', 31 | 'password.required' => '密码不能为空', 32 | ]; 33 | } 34 | } 35 | 36 | # 在控制器中使用 37 | class Post extends Controller { 38 | 39 | public function store(PostRequest $request) 40 | { 41 | 42 | } 43 | } 44 | ``` 45 | 46 | ### 3. 获取错误信息 47 | 48 | 在 Validator 实例上调用 `errors` 方法后 .`$errors` 变量是自动提供给所有视图的 `MessageBag` 类的一个实例。 49 | 50 | ```php 51 | $errors->first("username");//获取username的错误信息 52 | $errors->all();//所有的错误 53 | ``` 54 | 55 | 56 | 57 | ## 手动验证 58 | 59 | ### 1. 创建验证器 60 | 61 | 通过validator Facade创建验证.**make**方法 62 | 63 | ```php 64 | $validator = Validator::make($request->all(), [ 65 | 'title' => 'required|unique:posts|max:255', 66 | 'body' => 'required', 67 | ]); 68 | if($validator->fails) { 69 | //验证失败 70 | return redirect('post/create') 71 | ->withErrors($validator) 72 | ->withInput(); 73 | } 74 | ``` 75 | 76 | -------------------------------------------------------------------------------- /Laravel/View.md: -------------------------------------------------------------------------------- 1 | ## Laravel 2 | 3 | >视图默认存放在 resources/views 4 | 5 | - 判断视图文件是否 存在 6 | 7 | view()-> exists('posts.create') 8 | 9 | - 传递数据到视图 10 | 11 | return view('post.index',['name'=>'Jack']); 12 | return view('post.index')->with('name','jack'); 13 | 14 | - 把数据共享给所有视图 15 | >可以通过使用视图 factory 的 share 方法来完成.通常情况下,你会把这些调用 share 方法的代码放在一个服务提供者的 boot 方法内。你可以选择直接写在 AppServiceProvider 里,或是自己生成一个不同的服务提供者来放置这些代码 16 | 17 | public function boot() 18 | { 19 | view()->share('key', 'value'); 20 | } 21 | 22 | 23 | ### 视图组件 24 | 25 | > 视图组件就是在视图被渲染前,会被调用的闭包或类方法。如果你想在每次渲染某些视图时绑定数据,**视图组件可以帮你把这样的程序逻辑都组织到同一个地方。** 使用 View 辅助函数来获取底层 Illuminate\Contracts\View\Factory contract 实现 26 | 27 | 28 | 注册provice 29 | 30 | config/app.php 配置providers数组 31 | 32 | -------------------------------------------------------------------------------- /Laravel/auth.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/Laravel/auth.md -------------------------------------------------------------------------------- /Laravel/composer.md: -------------------------------------------------------------------------------- 1 | ## Composer 2 | 3 | > composer php 包管理器 类似node的npm p 4 | 5 | -------------------------------------------------------------------------------- /Laravel/down.md: -------------------------------------------------------------------------------- 1 | ## Laravel 维护模式 2 | 3 | 4 | > 当你的应用程序处于维护模式时,所有传递至应用程序的请求都会显示出一个自定义视图 5 | > 6 | 7 | php artisan down #启用维护模式 8 | 9 | php artisan up 关闭维护模式 10 | 11 | 维护模式的相应的模板在 resources/views/errors/503.blade.php 12 | 13 | > 处于维护模式中,所有的队列将不会处于工作中。 14 | 15 | -------------------------------------------------------------------------------- /Laravel/environment.md: -------------------------------------------------------------------------------- 1 | ## Laravel environment 2 | 3 | > 获取环境信息 4 | 5 | app()->environment() 6 | App::environment(); 7 | 8 | > 判断环境是否是local 9 | 10 | app()->environment('local') -------------------------------------------------------------------------------- /Laravel/laravel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/Laravel/laravel.png -------------------------------------------------------------------------------- /Linux/Centos升级git.md: -------------------------------------------------------------------------------- 1 | ## centos升级git 2 | 3 | centos 默认是很老的1.7.需要更换成最新的git版本 4 | 5 | ### 1. 安装依赖 6 | 7 | ```bash 8 | # yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel 9 | # yum install gcc perl-ExtUtils-MakeMaker 10 | ``` 11 | 12 | ### 2. 卸载git 13 | 14 | ```bash 15 | yum remove git 16 | ``` 17 | 18 | ### 3.下载最新的git 19 | 20 | ```bash 21 | # cd /usr/src 22 | # wget https://github.com/git/git/archive/v2.17.1.tar.gz 23 | # tar xzf v2.17.1.tar.gz 24 | ``` 25 | 26 | ### 4. 编译安装 27 | 28 | ```bash 29 | # cd v2.17.1 30 | # make prefix=/usr/local/git all 31 | # make prefix=/usr/local/git install 32 | # echo "export PATH=$PATH:/usr/local/git/bin" >> /etc/bashrc 33 | # source /etc/bashrc 34 | ``` 35 | 36 | -------------------------------------------------------------------------------- /Linux/C语言指针.md: -------------------------------------------------------------------------------- 1 | 2 | ## 指针 3 | 4 | C语言指针是指向内存的空间地址。内存一个有序列。从0x00000开始。而指针就是指向这个位置。 5 | 6 | 简单的说指针就是地址。 7 | 8 | 内存中的地址是存放变量的值。 9 | 10 | 取变量的地址 & 11 | 12 | 13 | ``` 14 | int a = 10; 15 | 16 | printf("%d",&a); //&a取a地址 17 | 18 | 19 | ``` 20 | 21 | 22 | 指针变量 23 | 24 | *a 定义一个指针变量。 使用\*可以取 变量的值。 25 | 26 | ``` 27 | 28 | int *a 29 | 30 | int b = 10; 31 | 32 | *a = 10 33 | 34 | printf("%d",a); 35 | 36 | ``` 37 | 38 | 指针和字符串 39 | 40 | 一个字符串的尾部由\0结束 41 | 数组的名字赋值给指针,指针指向第一个元素。 42 | 43 | ``` 44 | 45 | char arr[] = "hello";//字符串变量 46 | 47 | arr[1] = 'c'; //可以修改 48 | 49 | char *p = arr;//p指向 h 50 | 51 | 52 | char *arr = "hello";//字符串常量 不可更改 53 | 54 | arr[0] = 'c';//报错 55 | ``` -------------------------------------------------------------------------------- /Linux/LInux--history命令.md: -------------------------------------------------------------------------------- 1 | ## history 命令 2 | 3 | history 命令可以查看最近使用的命令。 4 | 5 | history 10 查询最近的10条 6 | 7 | history -c 可以清除以前的记录 -------------------------------------------------------------------------------- /Linux/Linux 命令.md: -------------------------------------------------------------------------------- 1 | ## tail 2 | 3 | 默认显示最后10行 4 | 5 | tail -n 24 可以指定显示行数 6 | 7 | 8 | ## wc 9 | 10 | 统计一个文件的行数 11 | 12 | wc -l 文件名 13 | 14 | ## head 15 | 16 | 查看文件的前多少行 17 | head -n100 filename -------------------------------------------------------------------------------- /Linux/Linux【dev-null】.md: -------------------------------------------------------------------------------- 1 | ## Shell中的>/dev/null 2>&1 与 2>&1 >/dev/null 与&>/dev/null 的区别 2 | 3 | 默认情况下,总是有三个文件处于打开状态,标准输入(键盘输入)、标准输出(输出到屏幕)、标准错误(也是输出到屏幕),它们分别对应的文件描述符是0,1,2 。那么我们来看看下面的几种重定向方法的区别: 4 | 5 | **>/dev/null 2>&1** 6 | 7 | // 实际上,应该等同于这样: 1>/dev/null 2>/dev/null ,默认情况下就是1,标准输出,所以一般都省略。 而&符号,后面接的是必须的文件描述符。不能写成2>1,这样就成了标准错误重定向到文件名为1的文件中了,而不是重定向标准错误到标准输出中。所以这里就是:标准输出重定向到了/dev/null,而标准错误又重定向到了标准输出,**所以就成了标准输出和标准错误都重定向到了/dev/null** 8 | 9 | **2>&1 >/dev/null** 10 | 11 | // 咋一看,这个跟上面那个有啥区别呢,不也是标准错误重定向到标准输出,而标准输出重定向到/dev/null么? 最后不应该都重定向/dev/null么? 我是这么理解的!一条指令同一时刻要么产生标准错误,要么产生标准输出。 当产出标准错误的时候,因这个标准错误重定向到了标准输出,而标准输出是输出到屏幕。这个时候标准输出还没有被重定向到/dev/null,于是在屏幕上打印了。当产生标准输出时,那么它就不是标准错误,2>&1无效,于是标准输出重定向dev/null,不打印到屏幕。所以最终结果将是:**标准错误打印到屏幕,而标准输出不打印到屏幕。** -------------------------------------------------------------------------------- /Linux/Linux常用测试命令.md: -------------------------------------------------------------------------------- 1 | ## 常用测试命令 2 | 3 | -------------------------------------------------------------------------------- /Linux/Linux搭建socket服务器.md: -------------------------------------------------------------------------------- 1 | ## 搭建socket 5 服务器 ## 2 | 3 | > SOCKS是什么:防火墙安全会话转换协议 (Socks: Protocol for sessions traversal across firewall securely) SOCKS 协议提供一个框架,为在 TCP 和 UDP 域中的客户机/服务器应用程序能更方便安全地使用网络防火墙所提供的服务 4 | + 安装socks5 依赖 5 | 6 | yum install pam-devel openldap-devel openssl-devel 7 | 8 | + 下载soks5 源码包 编译安装 9 | 10 | > 最新版ss5-3.8.9-8 11 | 下载地址 :[https://sourceforge.net/projects/ss5/files/](https://sourceforge.net/projects/ss5/files/) 12 | 13 | > tar zxvf ss5-3.8.9-8.tar.gz 14 | > cd ss5-3.8.9-8 15 | > ./configure && make && make install 16 | 17 | + 修改配置 18 | > ss5的配置在 /etc/opt/ss5 下 19 | 20 | 1. 增加用户名和密码 21 | > vi ss5.passwd #每一行 一个用户名和密码 用空格分割 如 admin admin 22 | 2. 修改配置 23 | > vi ss5.conf 24 | #auth 0.0.0.0/0 - - 25 | #去掉注释,改为 26 | auth 0.0.0.0/0 - u 27 | #permit - 0.0.0.0/0 - 0.0.0.0/0 - - - - - 28 | #去掉注释: 29 | permit - 0.0.0.0/0 - 0.0.0.0/0 - - - - - 30 | > u:使用ss5.passwd帐号密码登录,-:默认任何人都可使用 31 | 32 | + 启动ss5 33 | 34 | > chmod 777 /etc/rc.d/init.d/ss5 35 | > /etc/rc.d/init.d/ss5 start 36 | 37 | 38 | -------------------------------------------------------------------------------- /Linux/Llinux (sudouser).md: -------------------------------------------------------------------------------- 1 | 破解Ubuntu root密码 2 | 3 | 4 | 1. 重启系统 5 | 2. 启动时按shift,选择recovery mode,此时会有一个选项:Advanced Options for Ubuntu, 选中直接回车 6 | 7 | 3. 删除recovery \nomodeset 8 | 9 | 4. 在这行的最后添加 quiet splash rw init=/bin/bash 10 | 11 | 5. 按F10, 启动。 12 | 6. /etc/sudoers默认是只读文件,所以先改变他的属性,输入chmod 440 /etc/sudoers 13 | 4,如果提示没有权限,或者不允许修改,就先输入 14 | mount -o remount rw / 15 | 然后更改权限即可。 16 | 如果内容有错误,可以vi /etc/sudoers 进入修改。或者将以前添加的错误部分删除再保存 17 | 18 | 19 | ## 让用户sudo的时候不加密码 20 | 3.编辑sudoers文件 21 | vi /etc/sudoers 22 | 找到这行 root ALL=(ALL) ALL,在他下面添加xxx ALL=(ALL) ALL (这里的xxx是你的用户名) 23 | 24 | ps:这里说下你可以sudoers添加下面四行中任意一条 25 | youuser ALL=(ALL) ALL 26 | %youuser ALL=(ALL) ALL 27 | youuser ALL=(ALL) NOPASSWD: ALL 28 | %youuser ALL=(ALL) NOPASSWD: ALL 29 | 30 | 第一行:允许用户youuser执行sudo命令(需要输入密码). 31 | 第二行:允许用户组youuser里面的用户执行sudo命令(需要输入密码). 32 | 第三行:允许用户youuser执行sudo命令,并且在执行的时候不输入密码. 33 | 第四行:允许用户组youuser里面的用户执行sudo命令,并且在执行的时候不输入密码. -------------------------------------------------------------------------------- /Linux/MAC下安装Sqlrv拓展.md: -------------------------------------------------------------------------------- 1 | 在mac下需要连接SqlServer数据。需要安装拓展 2 | ### 1. 下载最新的编译好的拓展。 3 | [https://github.com/Microsoft/msphpsql/releases](https://github.com/Microsoft/msphpsql/releases) 4 | 5 | ### 2. 安装odbc driver 13 6 | ```bash 7 | $ brew tap microsoft/mssql-release https://github.com/Microsoft/homebrew-mssql-release 8 | $ brew update 9 | $ brew install --no-sandbox msodbcsql@13.1.9.2 mssql-tools@14.0.6.0 10 | ``` 11 | 12 | 参考文档 13 | - [https://github.com/Microsoft/msphpsql](https://github.com/Microsoft/msphpsql) 14 | - [安装 Linux 和 macOS 上的 Microsoft ODBC Driver for SQL Server](https://docs.microsoft.com/zh-cn/sql/connect/odbc/linux-mac/installing-the-microsoft-odbc-driver-for-sql-server?view=sql-server-2017#microsoft-odbc-driver-131-for-sql-server) 15 | -------------------------------------------------------------------------------- /Linux/Nginx Fpm出现access deny错误.md: -------------------------------------------------------------------------------- 1 | NGINX Fpm出现access deny错误 2 | 3 | 在stackoverflow.com找到的答案 4 | 5 | 6 | 1. In your php-fpm www.conf set security.limit_extensions to .php or .php5 or whatever suits your environment. For some users, completely removing all values or setting it to FALSE was the only way to get it working. 7 | In your nginx config file set fastcgi_pass to your socket address (e.g. unix:/var/run/php-fpm/php-fpm.sock;) instead of your server address and port. 8 | Check your SCRIPT_FILENAME fastcgi param and set it according to the location of your files. 9 | In your nginx config file include fastcgi_split_path_info ^(.+\.php)(/.+)$; in the location block where all the other fastcgi params are defined. 10 | In your php.ini set cgi.fix_pathinfo to 1 11 | 12 | 大概的检查步骤 13 | 14 | 1. 检查phpfpm的配置,security.limit_extensions是否允许php文件、 15 | 2. 配置nginx 的fastcgi_pass 为unix:/xxx/xxx/php.socket 16 | 3. 如果配置中打开了fastcgi_split_path_info ^(.+\.php)(/.+)$; 那么 需要再php.ini中设置一下==cgi.fix_pathinfo=1== -------------------------------------------------------------------------------- /Linux/Nginx location.md: -------------------------------------------------------------------------------- 1 | 在nginx中配置proxy_pass时,当在后面的url加上了/,相当于是绝对根路径, 2 | 则nginx不会把location中匹配的路径部分代理走;如果没有/,则会把匹配的路径部分也给代理走。 3 | 首先是location进行的是模糊匹配 4 |     1)没有“/”时,location /abc/def可以匹配/abc/defghi请求,也可以匹配/abc/def/ghi等 5 |     2)而有“/”时,location /abc/def/不能匹配/abc/defghi请求,只能匹配/abc/def/anything这样的请求 6 | 下面四种情况分别用http://192.168.1.4/proxy/test.html 进行访问。 7 | 8 | 第一种: 9 | ``` 10 | location  /proxy/ { 11 | 12 | proxy_pass http://127.0.0.1:81/; 13 | 14 | } 15 | ``` 16 | 结论:会被代理到 `http://127.0.0.1:81/test.html`这个url 17 | 18 |   19 | 20 | 第二种(相对于第一种,最后少一个 /) 21 | ``` 22 | location  /proxy/ { 23 | 24 | proxy_pass http://127.0.0.1:81; 25 | 26 | } 27 | ``` 28 | 结论:会被代理到`http://127.0.0.1:81/proxy/test.html` 这个url 29 | 30 |   31 | 32 | 第三种: 33 | 34 | ``` 35 | location  /proxy/ { 36 | 37 | proxy_pass http://127.0.0.1:81/ftlynx/; 38 | 39 | } 40 | 41 | 结论:会被代理到`http://127.0.0.1:81/ftlynx/test.html` 这个url。 42 | ``` 43 |   44 | 45 | 第四种(相对于第三种,最后少一个 / ): 46 | ``` 47 | location  /proxy/ { 48 | 49 | proxy_pass http://127.0.0.1:81/ftlynx; 50 | 51 | } 52 | ``` 53 | 54 | 结论:会被代理到`http://127.0.0.1:81/ftlynxtest.html` 这个url 55 | 56 | 57 | ## Nginx location 配置的优先级 58 | 59 | - 1、表达式的几种形式 60 | ~ 表示执行一个正则匹配,区分大小写 61 | 62 | ~* 表示执行一个正则匹配,不区分大小写 63 | 64 | ^~ 表示普通字符匹配。使用前缀匹配。如果匹配成功,则不再匹配其他location。 65 | 66 | = 进行普通字符精确匹配。也就是完全匹配。 67 | 68 | @ 它定义一个命名的 location,使用在内部定向时,例如 error_page, try_files 69 | 70 | - 2、表达式之间的优先级 71 | 不同的表达式之间优先级不同,相同的表达式,匹配规则更长的优先级更高。 72 | 73 | > = 的优先级最高 74 | > ^~ 优先级次之 75 | > ~,~* 的优先级一致,次于^~ 76 | > 普通字符串匹配优先级最低 77 | 78 | ``` 79 | location =/ { 80 | } 81 | location ^~/api/ { 82 | 83 | } 84 | location ~/api/ { 85 | 86 | } 87 | location ~ \.php { 88 | 89 | } 90 | location /api { 91 | 92 | } 93 | ``` 94 | 95 | 96 | **尽管location 的优先级与配置文件的编写顺序没什么关系,但是最好还是按照优先级顺序编写配置文件,方便理解,排查问题 ** 97 | -------------------------------------------------------------------------------- /Linux/Shell/Shell(数组).md: -------------------------------------------------------------------------------- 1 | ## 数组 2 | 3 | shell数组主持一维数组。和php类似。不需要指定数组的大小。 4 | 5 | 数组用括号抱起来。每个元素用==空格==分割 6 | 7 | arr=(a1 a2 a3) 8 | 9 | ``` 10 | arr=(1 2 3 ) 11 | 12 | ${arr[0]}//1 13 | 14 | ``` 15 | 16 | - 获取数组所有的元素 17 | 18 | 使用@ 或 * 可以获取数组中的所有元素 19 | 20 | ``` 21 | ${arr[*]} 22 | 23 | ``` 24 | 25 | - 获取数组的长度 26 | 27 | ``` 28 | ${#arr[*]} 29 | 30 | ``` 31 | 32 | - 遍历数组 33 | 34 | 35 | ``` 36 | 37 | for a in ${arr[*]};do 38 | echo $a 39 | done 40 | ``` 41 | 42 | - 数组第n个元素的长度 43 | 44 | 45 | ``` 46 | ${#arr[2]} 47 | 48 | ``` 49 | 50 | - 数组切片 51 | 52 | 53 | ``` 54 | ${arr[*]:0:2} //1 2 55 | 56 | 57 | ``` 58 | 59 | - 数组搜索替换 60 | 61 | 62 | ``` 63 | ${arr[*]/3/5} 64 | ``` 65 | 66 | - 添加元素到数组 67 | 68 | 69 | ``` 70 | arr=("${arr[*]}" "test") 71 | ``` -------------------------------------------------------------------------------- /Linux/Shell/Shell(接收参数).md: -------------------------------------------------------------------------------- 1 | ## 通过命令行接收参数 2 | 3 | 在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数。 4 | 5 | ``` 6 | > bash test.sh test test2 7 | 8 | $0 代表脚本文件 //test.sh 9 | $1 代表第一个参数 //test 10 | $# 参数的个数 // 2 11 | $* 所有参数 12 | 13 | for i in $*; do 14 | echo $i 15 | done 16 | 17 | $$ 脚本运行的进程号 18 | 19 | $! 最后一个进程号 20 | $? 最后退出的状态 0 表示没有问题 21 | 22 | ``` -------------------------------------------------------------------------------- /Linux/Shell/linux命令-locate.md: -------------------------------------------------------------------------------- 1 | ## locate 2 | 3 | locate命令其实是`find -name`的另一种写法,但是要比后者快得多,原因在于它不搜索具体目录,而是搜索一个数据库`/var/lib/locatedb`,这个数据库中含有本地所有文件信息。Linux系统自动创建这个数据库,并且每天自动更新一次,所以使用locate命令查不到最新变动过的文件。为了避免这种情况,可以在使用locate之前,先使用updatedb命令,手动更新数据库 4 | 5 | 使用方法 6 | 7 | ``` 8 | 9 | locate [options] 参数 10 | 11 | locate -d /usr/local/db "hello.c" #指定db的目录 查找hello.c 12 | 13 | ``` 14 | 15 | options 16 | 17 | - -d<目录>或--database=<目录>:指定数据库所在的目录; 18 | - -u:更新slocate数据库; 19 | - --help:显示帮助; 20 | - --version:显示版本信息。 21 | - -i 不区分大小写 22 | 23 | 24 | ``` 25 | #查询nginx开头的文件。 \是一个全局的字符 26 | 27 | locate -i -d /var/lib/locatedb "\nginx" 28 | ``` 29 | 30 | 31 | ## updatedb 32 | 33 | updatedb 就是更新locatedb的数据库文件。 34 | 35 | 默认的数据库文件 存在/var/lib/locatedb 36 | 37 | ``` 38 | 39 | updatedb -U /usr/lcoal/db #指定对应的目录 40 | 41 | ``` 42 | 43 | -------------------------------------------------------------------------------- /Linux/Shell/shell (流程控制).md: -------------------------------------------------------------------------------- 1 | ## if 2 | 3 | ``` 4 | if [[condition]];then 5 | 6 | fi 7 | 8 | //if else 9 | 10 | if [[condition]]; then 11 | 12 | else 13 | 14 | fi 15 | 16 | # if elseif else 17 | 18 | if [[condition]];then 19 | 20 | 21 | elif [[condition]];then 22 | 23 | fi 24 | 25 | 26 | 27 | 28 | ``` 29 | 30 | ## for 31 | 32 | ``` 33 | 34 | for i in list1 list2 ;do 35 | echo $i 36 | done 37 | 38 | for i in 1 2 3 4;do 39 | 40 | echo $i 41 | done 42 | //1 2 3 4 43 | 44 | for (( i = 0; i < 10; i++ )); do 45 | echo $i 46 | done 47 | 48 | ``` 49 | 50 | ## while 51 | 52 | 53 | ``` 54 | 55 | while [[ condition ]]; do 56 | #statements 57 | done 58 | 59 | 60 | ``` 61 | 62 | ### 例子 63 | 64 | ``` 65 | #! /bin/bash 66 | 67 | a=10 68 | b=20 69 | 70 | # 判断数值 71 | if [[ $a -ne $b ]]; then 72 | echo "a 不等于b" 73 | fi 74 | 75 | # 判断字符串 76 | if [[ '$a' != '$b' ]]; then 77 | echo "1" 78 | fi 79 | 80 | # 判断文件 81 | 82 | if [[ -d "../doc" ]]; then 83 | echo "dirctory" 84 | fi 85 | 86 | if [[ ! -f "../routes" ]]; then 87 | echo "not a file" 88 | fi 89 | 90 | 91 | #while 92 | while [[ $a -gt 1 ]]; do 93 | #statements 94 | echo $a; 95 | # 条件 96 | let a-- 97 | done 98 | 99 | # for 100 | 101 | for i in "wo" "rds"; do 102 | echo $i 103 | done 104 | ``` -------------------------------------------------------------------------------- /Linux/Shell/shell(include文件).md: -------------------------------------------------------------------------------- 1 | ## inlcude 文件 2 | 3 | 在shell中有时候需要引入外部的脚本文件 我们需要使用下面的两种方式 4 | 5 | 6 | 1. .filenamet 7 | 8 | ``` 9 | . ./a.sh 10 | 11 | ``` 12 | 13 | 2. source filename 14 | 15 | 在文件中使用source 16 | 17 | 18 | ``` 19 | 20 | source ./a.sh 21 | ``` -------------------------------------------------------------------------------- /Linux/Shell/shell(函数).md: -------------------------------------------------------------------------------- 1 | ## 函数 2 | 3 | shell中的函数 定义如下 4 | 5 | 6 | ``` 7 | 其中function是可以省略的 8 | [function] functionName(){} 9 | 10 | function test(){ 11 | 12 | } 13 | 14 | test(){ 15 | 16 | } 17 | 18 | ``` 19 | 20 | - 函数的调用 21 | 22 | 23 | 函数的调用和其他语言的调用不太一样 24 | 25 | 26 | ``` 27 | function test() 28 | { 29 | echo "hello" 30 | } 31 | 32 | test #调用函数 33 | 34 | ``` 35 | 36 | - 函数的参数 37 | 38 | 39 | 函数的参数定义不需要在()中定义形参 只需要在调用使用传入即可 40 | 41 | $n n代表整数 $1是第一个参数 以此类推 42 | ``` 43 | function test() 44 | { 45 | echo $1 # 第一个参数 以此类推 46 | } 47 | 48 | test 22 //22 49 | ``` 50 | -------------------------------------------------------------------------------- /Linux/Shell/shell(字符串截取).md: -------------------------------------------------------------------------------- 1 | Linux 的字符串截取很有用。有八种方法。 2 | 3 | 假设有变量 var=http://www.aaa.com/123.htm 4 | 5 | 1. `#` 号截取,删除左边字符,保留右边字符。 6 | 7 | `echo ${var#*//}` 8 | 9 | 其中 var 是变量名,# 号是运算符,*// 表示从左边开始删除第一个 // 号及左边的所有字符 10 | 即删除 http:// 11 | 结果是 :www.aaa.com/123.htm 12 | 13 | 2. `##` 号截取,删除左边字符,保留右边字符。 14 | 15 | ``` 16 | echo ${var##*/} 17 | ``` 18 | ##*/ 表示从左边开始删除最后(最右边)一个 / 号及左边的所有字符 19 | 即删除 http://www.aaa.com/ 20 | 结果是 123.htm 21 | 22 | 3. %号截取,删除右边字符,保留左边字符 23 | 24 | ``` 25 | echo ${var%/*} 26 | ``` 27 | 28 | %/* 表示从右边开始,删除第一个 / 号及右边的字符 29 | 结果是:http://www.aaa.com 30 | 31 | 4. %% 号截取,删除右边字符,保留左边字符 32 | ``` 33 | echo ${var%%/*} 34 | ``` 35 | %%/* 表示从右边开始,删除最后(最左边)一个 / 号及右边的字符 36 | 结果是:http: 37 | 38 | 5. 从左边第几个字符开始,及字符的个数 39 | 40 | 41 | ``` 42 | echo ${var:0:5} 43 | ``` 44 | 45 | 其中的 0 表示左边第一个字符开始,5 表示字符的总个数。 46 | 结果是:http: 47 | 48 | 6. 从左边第几个字符开始,一直到结束。 49 | 50 | 51 | ``` 52 | echo ${var:7} 53 | ``` 54 | 55 | 56 | 其中的 7 表示左边第8个字符开始,一直到结束。 57 | 结果是 :www.aaa.com/123.htm 58 | 59 | 7. 从右边第几个字符开始,及字符的个数 60 | 61 | 62 | ``` 63 | echo ${var:0-7:3} 64 | ``` 65 | 66 | 其中的 0-7 表示右边算起第七个字符开始,3 表示字符的个数。 67 | 结果是:123 68 | 69 | 8. 从右边第几个字符开始,一直到结束。 70 | 71 | 72 | ``` 73 | echo ${var:0-7} 74 | ``` 75 | 76 | 77 | 表示从右边第七个字符开始,一直到结束。 78 | 结果是:123.htm 79 | 注:(左边的第一个字符是用 0 表示,右边的第一个字符用 0-1 表示) -------------------------------------------------------------------------------- /Linux/Shell/shell(运算符).md: -------------------------------------------------------------------------------- 1 | ## 关系运算符 2 | 3 | 关系运算符只支持数字 4 | 5 | ``` 6 | eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。 7 | -ne 检测两个数是否相等,不相等返回 true。 [ $a -ne $b ] 返回 true。 8 | -gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。 9 | -lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。 10 | -ge 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。 11 | -le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。 12 | 13 | ``` 14 | ``` 15 | 16 | a=10 17 | b=20 18 | 19 | if [[ $a eq $b ]];then 20 | echo "等于" 21 | fi 22 | 23 | ``` 24 | 25 | ## 布尔运算符 26 | 27 | ``` 28 | 29 | 运算符 说明 举例 30 | ! 非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。 31 | -o 或运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。 32 | -a 与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。 33 | 34 | ``` 35 | 36 | ## 文件测试符号 37 | 38 | ``` 39 | b file 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。 40 | -c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] 返回 false。 41 | -d file 检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。 42 | -f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。 43 | -g file 检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回 false。 44 | -k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回 false。 45 | -p file 检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ] 返回 false。 46 | -u file 检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回 false。 47 | -r file 检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。 48 | -w file 检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。 49 | -x file 检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。 50 | -s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。 51 | -e file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。 52 | ``` 53 | 54 | ``` 55 | file="" 56 | if [[-f $file ]]; then 57 | echo "is a file" 58 | fi 59 | ``` -------------------------------------------------------------------------------- /Linux/Shell/shell符号.md: -------------------------------------------------------------------------------- 1 | ## ? \# % 2 | 3 | 假设我们定义了一个变量为: 4 | ``` 5 | file=/dir1/dir2/dir3/my.file.txt 6 | 可以用${ }分别替换得到不同的值: 7 | ${file#*/}:删掉第一个/ 及其左边的字符串:dir1/dir2/dir3/my.file.txt 8 | ${file##*/}:删掉最后一个/ 及其左边的字符串:my.file.txt 9 | ${file#*.}:删掉第一个. 及其左边的字符串:file.txt 10 | ${file##*.}:删掉最后一个. 及其左边的字符串:txt 11 | ${file%/*}:删掉最后一个 / 及其右边的字符串:/dir1/dir2/dir3 12 | ${file%%/*}:删掉第一个/ 及其右边的字符串:(空值) 13 | ${file%.*}:删掉最后一个 . 及其右边的字符串:/dir1/dir2/dir3/my.file 14 | ${file%%.*}:删掉第一个 . 及其右边的字符串:/dir1/dir2/dir3/my 15 | 16 | 记忆的方法为: 17 | \# 是 去掉左边(键盘上#在 $ 的左边) 18 | %是去掉右边(键盘上% 在$ 的右边) 19 | 单一符号是最小匹配;两个符号是最大匹配 20 | ${file:0:5}:提取最左边的5 个字节:/dir1 21 | ${file:5:5}:提取第5 个字节右边的连续5个字节:/dir2 22 | 也可以对变量值里的字符串作替换: 23 | ${file/dir/path}:将第一个dir 替换为path:/path1/dir2/dir3/my.file.txt 24 | ${file//dir/path}:将全部dir 替换为path:/path1/path2/path3/my.file.txt 25 | 26 | 27 | 利用${ } 还可针对不同的变数状态赋值(沒设定、空值、非空值): 28 | ${file-my.file.txt} :假如$file 沒有设定,則使用my.file.txt 作传回值。(空值及非空值時不作处理) 29 | ${file:-my.file.txt} :假如$file 沒有設定或為空值,則使用my.file.txt 作傳回值。(非空值時不作处理) 30 | ${file+my.file.txt} :假如$file 設為空值或非空值,均使用my.file.txt 作傳回值。(沒設定時不作处理) 31 | ${file:+my.file.txt} :若$file 為非空值,則使用my.file.txt 作傳回值。(沒設定及空值時不作处理) 32 | ${file=my.file.txt} :若$file 沒設定,則使用my.file.txt 作傳回值,同時將$file 賦值為my.file.txt 。(空值及非空值時不作处理) 33 | ${file:=my.file.txt} :若$file 沒設定或為空值,則使用my.file.txt 作傳回值,同時將$file 賦值為my.file.txt 。(非空值時不作处理) 34 | ${file?my.file.txt} :若$file 沒設定,則將my.file.txt 輸出至STDERR。(空值及非空值時不作处理) 35 | 36 | ${file:?my.file.txt} :若$file 没设定或为空值,则将my.file.txt 输出至STDERR。(非空值時不作处理) 37 | ${#var} 可计算出变量值的长度: 38 | 39 | ${#file} 可得到27 ,因为/dir1/dir2/dir3/my.file.txt 是27个字节 40 | ``` -------------------------------------------------------------------------------- /Linux/Ubuntu-soft.md: -------------------------------------------------------------------------------- 1 | ## Ubuntu 编辑应用程序菜单 2 | ```bash 3 | sudo apt-get install alacarte 4 | ``` 5 | ## Ubuntu 编辑grub 6 | ```bash 7 | sudo add-apt-repository ppa:danielrichter2007/grub-customizer 8 | sudo apt-get update 9 | sudo apt-get install grub-customizer 10 | ``` 11 | -------------------------------------------------------------------------------- /Linux/Ubuntu关闭触摸板.md: -------------------------------------------------------------------------------- 1 | ## Ubuntu关闭触摸板 2 | 3 | 4 | 有时候在笔记本使用Ubuntu,触摸板经常会碰到。所以就想关闭。以下是方法 5 | 6 | ``` 7 | #关闭触摸板: 8 | 9 | sudo modprobe -r psmouse 10 | 11 | #打开触摸板: 12 | 13 | sudo modprobe psmouse 14 | 15 | ``` -------------------------------------------------------------------------------- /Linux/Ubuntu更新ppa.md: -------------------------------------------------------------------------------- 1 | Ubuntu更新ppa 2 | 3 | PPA源 4 | > Personal Package Archives(个人软件包档案)是Ubuntu Launchpad网站提供的一项服务,允许个人用户上传软件源代码,通过Launchpad进行编译并发布为2进制软件包,作为apt/新立得源供其他用户下载和更新。在Launchpad网站上的每一个用户和团队都可以拥有一个或多个PPA。 5 | 6 | PPA的一般形式是 7 | 8 | ppa:user/ppa-name 9 | 10 | 添加PPA源的命令为: 11 | 12 | sudo add-apt-repository ppa:user/ppa-name 13 | 14 | 删除一个ppa源 15 | 16 | sudo add-apt-repository -r ppa:user/ppa-name 17 | 18 | 搜索一个软件 19 | 20 | sudo apt-cache search php 21 | 22 | 安装一个软件 23 | 24 | sudo apt-get install php 25 | 26 | 27 | ## 查看Ubuntu 版本信息 28 | 29 | cat /etc/issue 30 | 31 | sudo lsb_release -a 32 | 33 | ## 查看linux内核 34 | 35 | uname -r -------------------------------------------------------------------------------- /Linux/Ubuntu更新系统.md: -------------------------------------------------------------------------------- 1 | 首先更新一下系统: 2 | 3 | sudo apt-get update 4 | 5 | sudo apt-get dist-upgrade 6 | 7 | 接下来,需要安装更新管理器的核心: 8 | 9 | sudo apt-get install update-manager-core 10 | 11 | sudo do-release-upgrade -d 12 | 13 | 对命令做一下解释:d-release-upgrade 命令是帮助我们寻找最新的稳定版本,而 -d 参数意思是包括非稳定版本 -------------------------------------------------------------------------------- /Linux/VIM(设置tab四个空格).md: -------------------------------------------------------------------------------- 1 | ## vim tab设置为4个空格 2 | 3 | 在.vimrc中添加以下代码后,重启vim即可实现按TAB产生4个空格: 4 | set ts=4 (注:ts是tabstop的缩写,设TAB宽4个空格) 5 | set expandtab 6 | 7 | 对于已保存的文件,可以使用下面的方法进行空格和TAB的替换: 8 | **TAB替换为空格:** 9 | :set ts=4 10 | :set expandtab 11 | :%retab! 12 | 13 | **空格替换为TAB:**:set ts=4 14 | :set noexpandtab 15 | :%retab! -------------------------------------------------------------------------------- /Linux/crontab每小时执行一次.md: -------------------------------------------------------------------------------- 1 | ## crontab 每隔一个小时执行一次 2 | 3 | 按照crontab的写法。 4 | 5 | 网上的写法 6 | 7 | ```shell 8 | 0 */1 * * * 9 | * */1 * * * #错误的每隔一小时执行一次,事实上每分钟执行一次 10 | 11 | ``` 12 | 13 | 14 | 15 | 其实这都是错的。第一个是每个小时的零点执行,第二种是每分钟执行。这个很坑。 16 | 17 | **真正的按一个小时执行** 18 | 19 | 我们让计划任务按每60分钟执行一次 20 | 21 | ```shell 22 | */60 * * * * #每60分钟即每小时执行一次 23 | ``` 24 | 25 | -------------------------------------------------------------------------------- /Linux/file_stat.md: -------------------------------------------------------------------------------- 1 | ```shell 2 | #!/bin/bash 3 | 4 | a=`stat -c %Y /var/tomcat/logs/catalina.out` //获取文件的修改时间(秒为单位) 5 | 6 | b=`date +%s` //获取当前系统的时间 (秒为单位) 7 | 8 | if [ $[ $b - $a ] -gt 1800 ]; //判断当前时间和文件修改时间差(30分钟) 9 | 10 | then 11 | 12 | /sbin/service tomcat restart //执行的操作:重启tomcat服务 13 | 14 | fi 15 | -------------------------------------------------------------------------------- /Linux/git撤销记录.md: -------------------------------------------------------------------------------- 1 | ## git删除提交历史 2 | 3 | 在我们开发的过程中,有时候偶尔不小心把敏感信息也提交到远程仓库了,这个时候如果再修改,再提交敏感信息还是存在历史记录中。我们可以通过回退和强制刷新远程版本库来解决 4 | 5 | ```bash 6 | git log #查看记录 7 | git reset --hard HEAD 8 | git add . 9 | git commit -m '注释' 10 | git push origin --force --all# 强制刷新远程库 11 | git push origin --force --tags 12 | ``` 13 | 14 | -------------------------------------------------------------------------------- /Linux/linuxcomand.md: -------------------------------------------------------------------------------- 1 | > 检查远程端口是否对bash开放 2 | 3 | echo > /dev/tcp/8.8.8.8/53 && echo "open" 4 | 5 | >让进程进入后台 6 | 7 | ctrl+z 8 | 9 | > 让进程转入前台 10 | 11 | fg 12 | 13 | > 产生随机的十六进制数,其中n是字符数 14 | 15 | openssl rand -hex n 16 | 17 | > 在当前shell里执行一个文件里的命令 18 | 19 | source /home/user/file.name 20 | 21 | > 截取前五个字符 22 | 23 | ${variable:0:5} 24 | 25 | >SSH debug 模式 26 | 27 | ssh -vvv user@ip 28 | 29 | > ssh with pem key 30 | 31 | ssh user@ip-add -i key.pem 32 | 33 | > 用wget 抓取整个网站的目录、 34 | 35 | wget -r --no-parent --reject "index.html*" http://host -P /home/user/ 36 | 37 | > 一次创建多个目录 38 | 39 | mkdir -P /home/{dr1,dr2} 40 | 41 | > 列出包括子进程的进程树 42 | 43 | ps axwef 44 | 45 | >创建war文件 46 | 47 | jar -cvf name.war file 48 | 49 | > 测试硬盘写入速度 50 | 51 | dd if=/dev/zero of=/tmp/output.img bs=8k 52 | count=256k; rm -rf /tmp/output.img 53 | 54 | >测试硬盘读取速度 55 | 56 | hdpara -Tt /dev/sda 57 | 58 | >获取文本的md5hash 59 | 60 | echo -n "test" | md5sum 61 | > 检查xml 格式 62 | 63 | xmllint --noout file.xml 64 | 65 | > 将tar.gz提取到新目录 66 | 67 | tar zxvf pa.tar.gz -C new_dir 68 | 69 | > 使用curl 获取http的信息 70 | 71 | curl -I http://www.qq.com 72 | >修改文件或者目录的时间戳 73 | 74 | touch -t timestamp file 75 | 76 | >利用wget 进行ftp下载 77 | 78 | wget -m ftp://user:pass@host 79 | 80 | > -------------------------------------------------------------------------------- /Linux/nginx_code.md: -------------------------------------------------------------------------------- 1 | 50x 错误 2 | 3 | ### 1. 500 服务器内部错误 4 | 5 | 服务器500错误是服务器的内部错误. 6 | 可能原因 7 | 1. 程序语言错误,例如:PHP语法错误; 8 | 2. 高并发导致,系统资源限制不能打开过多的文件所致; 9 | 10 | 11 | ### 2. 502 Bad Gateway 12 | 13 | 502错误是WEB服务器故障,可能是由于程序进程不够,请求的php-fpm已经执行,但是由于某种原因而没有执行完毕,最终导致php-fpm进程终止。 14 | 15 | 可能原因: 16 | 1. php-cgi进程数不够用; 17 | 2. PHP执行时间过长; 18 | 3. php-cgi进程死掉; 19 | 20 | ### 3. 504 Gateway timeout 21 | 22 | 服务器504错误表示超时,是指客户端所发出的请求没有到达网关,例如请求没有到可以执行的php-fpm。一般是Nginx配置问题 23 | 24 | ### 4. 499 Client Closed Request 25 | 26 | ``` 27 | ngx_string(ngx_http_error_495_page), /* 495, https certificate error */ 28 | ngx_string(ngx_http_error_496_page), /* 496, https no certificate */ 29 | ngx_string(ngx_http_error_497_page), /* 497, http to https */ 30 | ngx_string(ngx_http_error_404_page), /* 498, canceled */ 31 | ngx_null_string, /* 499, client has closed connection */ 32 | ``` 33 | 34 | Nginx定义的一个状态码,用于表示这样的错误:服务器返回http头之前,客户端就提前关闭了http连接 35 | 36 | 可能问题: 37 | 38 | 1. 后台PHP程序处理请求时间过长 39 | 2. mysql慢查询 40 | 41 | 42 | -------------------------------------------------------------------------------- /Linux/nginx负载均衡.md: -------------------------------------------------------------------------------- 1 | ## Nginx 负载均衡配置 2 | 3 | > 配置后端的机器,nginx 的 upstream默认是以轮询的方式实现负载均衡,这种方式中,每个请求按时间顺序逐一分配到不同的后端服务器 4 | 5 | upstream backend { 6 | 7 | server 192.168.1.251; 8 | 9 | server 192.168.1.252; 10 | 11 | server 192.168.1.247; 12 | 13 | } 14 | 15 | > 配置反向代理 16 | 17 | location / { 18 | 19 | #设置主机头和客户端真实地址,以便服务器获取客户端真实IP 20 | proxy_set_header Host $host; 21 | proxy_set_header X-Real-IP $remote_addr; 22 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 23 | #禁用缓存 24 | proxy_buffering off; 25 | #反向代理的地址 26 | proxy_pass http://backend; 27 | 28 | } 29 | 30 | } 31 | 32 | ### Nginx 负载的几种方式 33 | 34 | 1.1 轮询 35 | 36 | > 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。 37 | 38 | upstream backend { 39 | 40 | server 192.168.1.251; 41 | 42 | server 192.168.1.252; 43 | 44 | server 192.168.1.247; 45 | 46 | } 47 | 1.2 权重(weight) 48 | 49 | > 指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况 50 | 51 | upstream bakend { 52 | server 192.168.159.10 weight=1; 53 | server 192.168.159.11 weight=10; 54 | } 55 | 56 | 1.3 ip_hash 57 | 58 | > 每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题 59 | 60 | upstream bakend{ 61 | ip_hash; 62 | server 192.168.159.10:8080; 63 | server 192.168.159.11:8080; 64 | } 65 | 1.4 fair 66 | 67 | > 按后端服务器的响应时间来分配请求,响应时间短的优先分配 68 | 69 | upstream bakend{ 70 | server 192.168.159.10:8080; 71 | server 192.168.159.11:8080; 72 | fair; 73 | } -------------------------------------------------------------------------------- /Linux/sed删除注释行.md: -------------------------------------------------------------------------------- 1 | 使用sed 快速删除以 `#` 的注释行 2 | 如果直接使用`sed -i /^#/d /path/to/file` 3 | 对于 空白开头 后面跟着`#`的文件并没有作用 4 | ``` 5 | #方法1 6 | sed -e -i '/^[ \t]*#/d' 7 | #方法2 8 | sed -i -c -e '/^[[:blank:]]*#/d' api.yaml 9 | ``` 10 | -------------------------------------------------------------------------------- /Linux/svn.md: -------------------------------------------------------------------------------- 1 | ## Centos 搭建svn服务器 2 | > 环境:Centos 6.4 3 | 4 | ### 安装svn 5 | 6 | yum -y install subversion 7 | 8 | ### 创建版本库目录 9 | 10 | mkdir -p /home/repos 11 | svnadmin create /home/repos/Test #创建Test 版本库 12 | 13 | ### 进入版本库 配置 14 | 15 | cd /home/repos/Test/conf 16 | 17 | >**conf** 下有三个文件 passwd、authz、svnserver.conf 18 | 19 | >authz 文件权限控制文件 20 | 21 | >passwd 账户密码文件 22 | 23 | >svnserve.conf 服务器配置文件 24 | 25 | 1.1 配置账户密码 26 | 27 | vi passwd 28 | 29 | 文件内容 30 | [users] 31 | admin=admin #每行一个用户名对应密码 32 | 1.2 配置svnserve.conf文件 33 | 34 | vi svnserve.conf 35 | 36 | [general] 37 | anon-access = no #匿名账户不允许访问 38 | auth-access = write#授权用户可以写入 39 | password-db = passwd#密码文件指向passwd文件 40 | authz-db = authz#授权配置指向authz 41 | realm = Test#版本库为Test 42 | 43 | 1.3 配置authz文件 44 | 45 | vi authz 46 | 47 | [/]#版本库根目录权限 48 | test1 = rw #用户test1 可以读写 49 | * = #其他用户没有权限 50 | 51 | ### 启动svn 52 | 53 | svnserve -d -r /home/repos/ 54 | 55 | ### 修改防火墙 56 | 57 | > svnserve 默认占用的是3690端,所有需要将3690放行 58 | 59 | vi /etc/sysconfig/iptables 60 | #加上下面的这句 61 | -A INPUT -m state --state NEW -m tcp -p tcp --dport 3690 -j ACCEPT 62 | #重启防火墙 63 | severice iptables restart 64 | 65 | -------------------------------------------------------------------------------- /Linux/同步,异步,阻塞,非阻塞.md: -------------------------------------------------------------------------------- 1 | # 同步,异步,阻塞,非阻塞 2 | 3 | ## 同步 4 | 5 | 同步是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。按照这个定义,其实绝大多数函数都是同步调用。 6 | 7 | 8 | ## 异步 9 | 10 | 当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。 11 | 12 | ## 阻塞 13 | 14 | 阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回 15 | 16 | ## 非阻塞 17 | 18 | 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。 19 | 20 | > 阻塞和非阻塞关注的是状态, 同步和异步关系的是结果。 21 | 22 | 举个例子。你去书店买书。老板告诉你有这本书。然后立即买了走了(同步),这个时候,如果没有书,你告诉老板,有了书打电话给我(异步)【你设置了一个回调在这,通知你】。 23 | 24 | 你去排队买东西。然后没有了这个东西,说这个东西需要多久有,你一直在这等,这就是阻塞了。后面的人就不能买了。如果你告诉服务器员了,有了再告诉我。我去忙其他的了。你离开了,后面的人依然可以买东西。然后不会阻塞在这里。 25 | 26 | 27 | 普通B/S模式(同步)AJAX技术(异步) 28 | 29 | 同步:提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事 30 | 31 | 异步: 请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完毕 32 | -------------------------------------------------------------------------------- /Linux/数据结构-树.md: -------------------------------------------------------------------------------- 1 | ## 二叉树 2 | 3 | ![image](http://pic002.cnblogs.com/images/2012/170818/2012062616014021.png) 4 | 5 | 6 | ### 1:术语 7 | 8 | 其实树中有很多术语的,这个是我们学习树形结构必须掌握的。 9 | 10 | <1> 父节点,子节点,兄弟节点 11 | 12 | 这个就比较简单了,B和C的父节点就是A,反过来说就是B和C是A的子节点。B和C就是兄弟节点。 13 | 14 | <2> 结点的度 15 | 16 | 其实”度“就是”分支数“,比如A的分支数有两个“B和C",那么A的度为2。 17 | 18 | <3> 树的度 19 | 20 | 看似比较莫名其妙吧,他和”结点的度“的区别就是,树的度讲究大局观,乃树中最大的结点度,其实也就是2。 21 | 22 | <4> 叶结点,分支结点 23 | 24 | 叶结点就是既没有左孩子也没有右孩子结点,也就是结点度为0。分支节点也就是if的else的条件咯。 25 | 26 | 27 | <5> 结点的层数 28 | 29 | 这个很简单,也就是树有几层。 30 | 31 | <6> 有序树,无序树 32 | 33 | 有序树我们先前也用过,比如“堆”和“二叉排序树”,说明这种树是按照一定的规则进行排序的,else条件就是无序树。 34 | 35 | <7> 森林 36 | 37 | 38 | 现实中,很多的树形成了森林,那在数据结构中,我们把上图的“A”节点砍掉,那么B,C子树合一起就是森林咯。 39 | 40 | ### 2: 二叉树的类型 41 | 42 | 二叉树中有两种比较完美的类型,“完全二叉树”和“满二叉树”。 43 | 44 | <1> 满二叉树 45 | 46 | 除叶子节点外,所有节点的度都为2,文章开头处的树就是这里的“满二叉树”。 47 | 48 | <2> 完全二叉树 49 | 50 | 必须要满足两个条件就即可: 干掉最后一层,二叉树变为“满二叉树”。 51 | 最后一层的叶节点必须是“从左到右”依次排开。 52 | 53 | 54 | ### 3: 二叉树的性质 55 | 56 | 二叉树中有5点性质非常重要,也是俺们必须要记住的。 57 | 58 | - <1> 二叉树中,第i层的节点最多有2(i-1)个。 59 | 60 | - <2> 深度为k的二叉树最多有2k-1个节点。 61 | 62 | - <3> 二叉树中,叶子节点树为N1个,度为2的节点有N2个,那么N1=N2+1。 63 | 64 | - 4> 具有N个结点的二叉树深度为(Log2 N)+1层。 65 | 66 | - <5> N个结点的完全二叉树如何用顺序存储,对于其中的一个结点i,存在以下关系, 67 | 68 | 2*i是结点i的父结点。 69 | 70 | i/2是结点i的左孩子。 71 | 72 | (i/2)+1是结点i的右孩子 -------------------------------------------------------------------------------- /Linux/配置多个SSH-Key.md: -------------------------------------------------------------------------------- 1 | # 配置多个SSH-Key 2 | 3 | ### 1. 生成多个key 4 | 5 | ```shell 6 | ssh-keygen -t rsa -C "your_mail@example.com" -f github_rsa 7 | ssh-keygen -t rsa -C "your_mail@example.com" -f work_rsa 8 | 9 | ``` 10 | 11 | ### 2. 为配置文件添加config 12 | 13 | ```ini 14 | $ cd ~/.ssh/ 15 | $ touch config 16 | ``` 17 | 18 | 在config配置多个host 19 | 20 | ```ini 21 | #github 22 | Host github.com 23 | IdentityFile .ssh/github_rsa 24 | PreferredAuthentications publickey 25 | User root 26 | #work 27 | Host 188.1.1.1 28 | IdentityFile .ssh/work_rsa 29 | PreferredAuthentications publickey 30 | User root 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /Mysql/MySQL_join.md: -------------------------------------------------------------------------------- 1 | ## MySQL 几种 join 2 | 3 | 我们在使用MySQL的时候,经常需要进行`join` 表的操作,主要的`join` 有 **左连接**、**右连接**、**全连接**、**交叉连接** 4 | 一个表连接自己叫自连接 5 | 6 | 7 | 假设有两个表学生表和班级班 8 | 9 | 学生表 student 10 | 11 | | uid | uname | classid | 12 | | ---- | ----- | ------- | 13 | | 1 | 张三 | 1 | 14 | | 2 | 李四 | 2 | 15 | | 3 | 王二 | 3 | 16 | 17 | 班级表 class 18 | 19 | | classid | classname | 20 | | ------- | --------- | 21 | | 1 | 一班 | 22 | | 2 | 二班 | 23 | | 4 | 四班 | 24 | 25 | ### 1. 左外连接 LEFT JOIN 26 | 27 | ```sql 28 | select * from student left join class on student.classid = class.classid 29 | ``` 30 | 31 | | uid | uname | classid | classname | 32 | | ---- | ----- | ------- | --------- | 33 | | 1 | 张三 | 1 | 一班 | 34 | | 2 | 李四 | 2 | 二班 | 35 | | 3 | 王二 | 3 | null | 36 | 37 | ### 2. 右外连接 RIGHT join 38 | 39 | ```sql 40 | select * from student right join class on student.classid = class.classid 41 | ``` 42 | 43 | | uid | uname | classid | classname | 44 | | ---- | ----- | ------- | --------- | 45 | | 1 | 张三 | 1 | 一班 | 46 | | 2 | 李四 | 2 | 二班 | 47 | | null | null | 4 | 四班 | 48 | 49 | ### 3. 全外连接 FULL JOIN 50 | 51 | 全外连接返回参与连接的两个数据集合中的全部数据,无论它们是否具有与之相匹配的行 52 | 53 | ```sql 54 | select * from student full join class on class.classid = student.classid 55 | ``` 56 | 57 | ### 4. 自连接 58 | 59 | ```sql 60 | select * from student as a left join student as b on a.uid = b.uid 61 | ``` 62 | | uid | uname | classid | uid1 | uname1 | classid1 | 63 | | ---- | ----- | ------- | ---- | ----- | ------- | 64 | | 1 | 张三 | 1 | 1 | 张三 | 1 | 65 | | 2 | 李四 | 2 | 2 | 李四 | 2 | 66 | | 3 | 王二 | 3 | 3 | 王二 | 3 | 67 | 68 | -------------------------------------------------------------------------------- /Mysql/Mysql(in、join、exists).md: -------------------------------------------------------------------------------- 1 | 我们在写sql的时候,尽量不要使用使用子查询,而改成join或者exist 2 | 3 | ```sql 4 | select a.* from a where a.id (select b.id from b) 5 | ``` 6 | 7 | - 改成exist 8 | ```sql 9 | SELECT 10 | * 11 | FROM 12 | a 13 | WHERE 14 | EXISTS ( SELECT 1 FROM b WHERE a.id = b.id ) 15 | ``` 16 | - 改成join 17 | ```sql 18 | select a.* from a inner join b on a.id = b.id 19 | ``` 20 | ## NOT IN 改成 NOT EXIST/LEFT JOIN 21 | 22 | ```sql 23 | SELECT 24 | * 25 | FROM 26 | tbl1 27 | WHERE 28 | col3 NOT IN ( SELECT col3 FROM tbl2 ) 29 | ``` 30 | - 改成not exist 31 | 32 | ```sql 33 | SELECT 34 | * 35 | FROM 36 | tbl1 37 | WHERE 38 | NOT EXISTS ( SELECT 1 FROM tbl2 WHERE tbl1.col3 = tbl2.col3 ) 39 | ``` 40 | - 改成left join 41 | ```sql 42 | SELECT 43 | * 44 | FROM 45 | tbl1 46 | LEFT JOIN tbl2 ON tbl1.col3 = tbl2.col3 47 | WHERE 48 | tbl2.col3 IS NULL 49 | ``` 50 | -------------------------------------------------------------------------------- /Mysql/Mysql_autoincrement.md: -------------------------------------------------------------------------------- 1 | ## Mysql ID自增 2 | 3 | 我们在一般设计表的时候,用的`auto_increamnet` 几种操作会对这个auto_increment 造成影响 4 | 5 | ```sql 6 | CREATE TABLE `t1` ( 7 | `id` INT ( 10 ) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID,自增', 8 | `name` VARCHAR ( 20 ) NOT NULL DEFAULT '' COMMENT '用户昵称', 9 | PRIMARY KEY ( `id` ) 10 | ) ENGINE = INNODB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8 ; 11 | ``` 12 | 13 | ### 1. insert插入新数据 14 | 15 | ```sql 16 | insert into t(name) values('test') 17 | ``` 18 | 19 | 插入一条记录 会造成主键的自增,这是我们一般默认的,也是正常 20 | 21 | ### 2. Replace Into 22 | 23 | ```sql 24 | replace INTO t1 values (1,'test2') 25 | ``` 26 | 27 | **Affected rows: 2, Time: 0.001000s** 28 | 29 | replace into会导致auto_increment的值自增 30 | 31 | 32 | 33 | ### 3. INSERT ... ON DUPLICATE KEY UPDATE ...对主键的影响 34 | 35 | ``` 36 | INSERT INTO t1 37 | VALUES 38 | ( 1,"test") ON DUPLICATE KEY UPDATE NAME = 39 | VALUES 40 | ( NAME ); 41 | ``` 42 | 43 | 也会导致影响两行, 44 | 45 | -------------------------------------------------------------------------------- /Mysql/mysql三范式.md: -------------------------------------------------------------------------------- 1 | title: mysql三范式 2 | categories: mysql 3 | tags: [awstats] 4 | description: mysql三范式 5 | --- 6 | 7 | (1)第一范式(无重复的列) 8 | 9 | > 定义:数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项。如果实体中的某个属性有多> 个值时,必须拆分为不同的属性 10 | 11 | 例子解释: 12 | 班级:高三年1班,应改为2个字段,一个年级、一个班级,才满足第一范式 13 | 14 | (2)第二范式(属性完全依赖于主键) 15 | 16 | 定义:满足第一范式前提,当存在多个主键的时候,才会发生不符合第二范式的情况。 17 | 比如有两个主键,不能存在这样的属性,它只依赖于其中一个主键,这就是不符合第二范式 18 | 19 | 通俗理解:任意一个字段都只依赖表中的同一个字段 20 | 21 | 例子解释: 22 | 23 | 学生借书表: 24 | 学生证名称 学生证号 学生证办理时间 借书证名称 借书证号 借书证办理时间 25 | 26 | 应改为 27 | 1.学生证表: 28 | 学生证 学生证号 学生证办理时间 29 | 2.借书证表: 30 | 借书证 借书证号 借书证把你拉时间 31 | -------------------------------------------------------------------------------- /Mysql/mysql分组统计.md: -------------------------------------------------------------------------------- 1 | ## 按天、星期、月、季度、年进行分组统计 2 | 3 | 在开发的需求种,经常遇到一些各种需求,最近就遇到了这种按天、星期、月、季度的统计。 4 | 5 | 最初的想法,是把数据拿出来,然后用程序进行分组,但是后来想了想,还是用mysql的分组来实现。 6 | 7 | 假设有一个表`tc_case`, `create_time` 为时间戳 8 | 9 | ### 1. 按天 10 | 11 | ```sql 12 | select DATE_FORMAT(create_time,'%Y%m%d') days,count(id) as count from tc_case group by days; 13 | ``` 14 | 15 | ### 2. 按星期 16 | 17 | ```sql 18 | select DATE_FORMAT(create_time,'%Y%u') weeks,count(id) count from tc_case group by weeks; 19 | ``` 20 | 21 | ### 3. 按月 22 | 23 | ```sql 24 | select DATE_FORMAT(create_time,'%Y%m') months,count(id) count from tc_case group by months; 25 | ``` 26 | 27 | ### 4. 按季度 28 | 29 | ```sql 30 | select FLOOR((date_format(col, '%m')+2)/3)) as quarter,sum(views) from tc_case group by quarter; 31 | ``` 32 | 33 | ### 5. 按年 34 | 35 | ```sql 36 | select DATE_FORMAT(create_time,'%Y') year,count(id) as count from tc_case group by year; 37 | ``` 38 | 39 | -------------------------------------------------------------------------------- /Mysql/wait_timeout.md: -------------------------------------------------------------------------------- 1 | > MySQL中有一个名叫wait_timeout的变量,表示操作超时时间,当连接超过一定时间没有活动后,会自动关闭该连接,这个值默认为28800(即8小时) 2 | 一般我们在写程序的时候,如果出现mysql gone way 需要进行断线重连 3 | -------------------------------------------------------------------------------- /Mysql/算法基础知识.md: -------------------------------------------------------------------------------- 1 | 时间复杂度: 2 | 时间复杂度是指执行算法所需要的计算工作量。 3 | 4 | 一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。 一般情况下,算法的基本操作重复执行的次数是模块n的某一个函数f(n) -------------------------------------------------------------------------------- /Nodejs/Nodejs--DNS模块.md: -------------------------------------------------------------------------------- 1 | ## DNS模块 2 | 3 | 4 | > DNS模块 -------------------------------------------------------------------------------- /Nodejs/Nodejs--Os模块.md: -------------------------------------------------------------------------------- 1 | ## OS模块 2 | 3 | 4 | > os 模块主要就是获取系统的信息 5 | 6 | - 引入os模块 7 | 8 | var os = require('os') 9 | 10 | - 获取操作系统的位数 11 | 12 | require('os').arch() 13 | 14 | - 获取cpu信息 15 | 16 | require('os').cpus() 17 | 18 | - 获取磁盘剩余大小 19 | 20 | require('os').freemem() 21 | 22 | - 获取主目录 23 | 24 | require('os').homedir() 25 | 26 | - 获取hostname 27 | 28 | require('os').hostname() 29 | 30 | 31 | - 获取网络接口信息 32 | 33 | require('os').networkInterfaces() 34 | 35 | - 获取操作系统的类型 36 | 37 | os.platform() 38 | 39 | - 获取操作系统的缓存目录 40 | 41 | os.tmpdir() 42 | 43 | - 获取操作系统的版本 44 | 45 | os.release() 46 | 47 | - 获取操作系统的类型 48 | 49 | os.type() 50 | 51 | - 获取操作系统用户的信息(Added in: v6.0.0) 52 | 53 | os.userInfo() -------------------------------------------------------------------------------- /Nodejs/Nodejs--Path模块.md: -------------------------------------------------------------------------------- 1 | ## path模块 2 | 3 | > path模块提供了很多的方法 用于解析路径 4 | 5 | - 获取路径中的文件名 6 | 7 | var path = require('path') 8 | path.basename('/www/index.php')//index.php 9 | path.basename('/www/index.php','.php')//index 10 | 11 | - 获取路径名 12 | 13 | path.dirname('/www/qq/test')// /www/qq/ 14 | 15 | - 获取文件后缀名 16 | 17 | path.extname('index.php') //php 18 | 19 | - 判断是否是绝对路径 20 | 21 | path.isAbsolute('/www/qq/') //true 22 | 23 | - 拼接路径 24 | 25 | path.join('/www','aa') // /www/aa 26 | 27 | - 解析路径 28 | 29 | path.parse('/www/aa/t.txt') 30 | 31 | // returns 32 | // { 33 | // root : "/", 34 | // dir : "/www/aa/", 35 | // base : "t.txt", 36 | // ext : ".txt", 37 | // name : "file" 38 | // } -------------------------------------------------------------------------------- /Nodejs/Nodejs-事件对象.md: -------------------------------------------------------------------------------- 1 | ## Nodejs Events模块 2 | 3 | > Node.js 所有的异步 I/O 操作在完成时都会发送一个事件到事件队列。 4 | Node.js里面的许多对象都会分发事件:一个net.Server对象会在每次有新连接时分发一个事件, 一个fs.readStream对象会在文件被打开的时候发出一个事件。 所有这些产生事件的对象都是 events.EventEmitter 的实例。 5 | 6 | > Events模块只提供了一个对象EventEmitter 7 | 8 | 9 | - 创建一个events对象 10 | 11 | // 引入 events 模块 12 | var events = require('events'); 13 | // 创建 eventEmitter 对象 14 | var eventEmitter = new events.EventEmitter(); 15 | 16 | - 注册一个监听器 17 | 18 | eventEmitter.on('connection',function(){ 19 | 20 | }) 21 | 22 | - 触发监听 emit 23 | 24 | eventEmitter.emit('connection'); 25 | 26 | - 绑定一个监听 27 | 28 | eventEmitter.addListener('connection', listener1); 29 | 30 | - 移除一个监听事件 31 | 32 | eventEmitter.removeListener('connection', listener1); 33 | 34 | - 移动所有的监听事件 removeAllListeners 35 | 36 | eventEmitter.removeAllListeners('connection') 37 | 38 | - 获取监听器的数量 39 | 40 | console.log(eventEmitter.listenerCount('connection')) 41 | 42 | - 获取监听器的数组 43 | 44 | eventEmitter.listeners() 45 | 46 | - 获取最大监听器的数量 47 | 48 | eventEmitter.getMaxListeners()//默认是10 -------------------------------------------------------------------------------- /OpenAPI/01-通用信息.md: -------------------------------------------------------------------------------- 1 | ## API通用信息 2 | 3 | 将API的一般信息纳入规范被认为是一种很好的做法:版本号,许可证说明,联系人数据,文档链接等。我们特别建议为公共可用的API执行此操作; 因为这可以增加用户对服务的信心,贵公司提供。 4 | 5 | 要指定API元数据,请使用顶级`info`对象的属性: 6 | 7 | ```yaml 8 | openapi: 3.0.0 9 | info: 10 | 11 | # You application title. Required. 12 | title: Sample Pet Store App 13 | 14 | # API version. You can use semantic versioning like 1.0.0, 15 | # or an arbitrary string like 0.99-beta. Required. 16 | version: 1.0.0 17 | 18 | # API description. Arbitrary text in CommonMark or HTML. 19 | description: This is a sample server for a pet store. 20 | 21 | # Link to the page that describes the terms of service. 22 | # Must be in the URL format. 23 | termsOfService: http://example.com/terms/ 24 | 25 | # Contact information: name, email, URL. 26 | contact: 27 | name: API Support 28 | email: support@example.com 29 | url: http://example.com/support 30 | 31 | # Name of the license and a URL to the license description. 32 | license: 33 | name: Apache 2.0 34 | url: http://www.apache.org/licenses/LICENSE-2.0.html 35 | 36 | # Link to the external documentation (if any). 37 | # Code or documentation generation tools can use description as the text of the link. 38 | externalDocs: 39 | description: Find out more 40 | url: http://example.com 41 | ``` 42 | 43 | `title`和`version`属性是必需的,其他都是可选的。 44 | 45 | -------------------------------------------------------------------------------- /OpenAPI/13-标签分组.md: -------------------------------------------------------------------------------- 1 | ## 用标签分组操作 2 | 3 | 您可以`tags`为每个API操作分配一个列表。标记的操作可能由工具和库以不同方式处理。例如,Swagger UI用于`tags`对显示的操作进行分组。 4 | 5 | ```yaml 6 | tags: 7 | - name: pets 8 | description: Everything about your Pets 9 | externalDocs: 10 | url: http://docs.my-api.com/pet-operations.htm 11 | - name: store 12 | description: Access to Petstore orders 13 | externalDocs: 14 | url: http://docs.my-api.com/store-orders.htm 15 | paths: 16 | /pet/findByStatus: 17 | get: 18 | summary: Finds pets by Status 19 | tags: 20 | - pets 21 | ... 22 | /pet: 23 | post: 24 | summary: Adds a new pet to the store 25 | tags: 26 | - pets 27 | ... 28 | /store/inventory: 29 | get: 30 | summary: Returns pet inventories 31 | tags: 32 | - store 33 | ... 34 | ``` 35 | 36 | 全局标签部分中的标签顺序也控制了Swagger UI中的默认排序。 37 | 38 | 请注意,即使在根级别上未定义,也可以在操作中使用标签。 -------------------------------------------------------------------------------- /PHP/IIS7下,显示PHP错误(how to display php errors on iis7 or iis7.5).md: -------------------------------------------------------------------------------- 1 | ## IIS7下,显示PHP错误(how to display php errors on iis7 or iis7.5) 2 | 3 | 在php.ini中打开以下配置 4 | 5 | ``` 6 | display_errors = on; 7 | error_reporting = E_ALL & ~E_NOTICE; 8 | 9 | ``` 10 | 11 | 在网站的根目录下面加入以下web.config配置 12 | 13 | ``` 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | ``` -------------------------------------------------------------------------------- /PHP/Laravel/Laravel源码分析.md: -------------------------------------------------------------------------------- 1 | ## lavale源码分析。 2 | 3 | 先从入口的index.php中 4 | 5 | 6 | require __DIR__.'/../bootstrap/autoload.php'; 加载composer 中的自动加载的依赖 7 | 8 | $app = require_once __DIR__.'/../bootstrap/app.php'; 9 | 10 | 11 | 12 | app.php 13 | 14 | $app = new Illuminate\Foundation\Application( 15 | realpath(__DIR__.'/../') 16 | ); // 创建一个container 并设置程序的路径 17 | 18 | 19 | -------------------------------------------------------------------------------- /PHP/PHP 7 错误处理.md: -------------------------------------------------------------------------------- 1 | PHP 7 改变了大多数错误的报告方式。不同于传统(PHP 5)的错误报告机制,现在大多数错误被作为 Error 异常抛出 2 | 3 | 4 | Error 类并非继承自 Exception 类,所以不能用 catch (Exception $e) { ... } 来捕获 Error。你可以用 catch (Error $e) { ... },或者通过注册异常处理函数( set_exception_handler())来捕获 Error 5 | 6 | try{ 7 | 8 | }catch( Throwable $e){ 9 | 10 | } 11 | 12 | 13 | ## 引用计数基本知识 14 | 15 | 16 | 每个php变量存在一个叫"zval"的变量容器中。一个zval变量容器,除了包含变量的类型和值,还包括两个字节的额外信息。第一个是"is_ref",是个bool值,用来标识这个变量是否是属于引用集合(reference set)。通过这个字节,php引擎才能把普通变量和引用变量区分开来,由于php允许用户通过使用&来使用自定义引用,zval变量容器中还有一个内部引用计数机制,来优化内存使用。第二个额外字节是"refcount",用以表示指向这个zval变量容器的变量(也称符号即symbol)个数 17 | 18 | 19 | $a = 'hello'; 20 | xdebug_debug_zval('a'); // refCount=1 is_ref=0 21 | $b = $a; 22 | xdebug_debug_zval('a'); // refCount=2 is_ref=0 23 | $c = &$a; 24 | xdebug_debug_zval('a'); // refCount=2 is_ref=1 25 | 26 | unset($b); 27 | 28 | xdebug_debug_zval('a');// refCount=2 is_ref =1 29 | 30 | ### 复合类型(Compound Types) 31 | 32 | array和 object类型的变量把它们的成员或属性存在自己的符号表中 33 | 34 | 35 | $a = array( 36 | 'meaning' => 'life', 37 | 'number' => 42 38 | ); 39 | xdebug_debug_zval( 'a' ); 40 | 41 | a(refCount=2,is_ref=0) 42 | meaning(refCount=1,is_ref=0) 43 | number(refCount=1,is_ref=0) -------------------------------------------------------------------------------- /PHP/PHP单元测试.md: -------------------------------------------------------------------------------- 1 | ## PHPunit安装 2 | 3 | > PHPUnit 6.1 需要 PHP 7,强烈推荐使用最新版本的 PHP.代码覆盖率分析报告功能需要 Xdebug(2.5.0以上) 4 | ### 1. 下载phpunit.phpar 5 | 6 | 下载地址:https://phar.phpunit.de/phpunit-6.1.phar 7 | 8 | - 在linux下将下载好的phpunit-6.1.phpar 移动到/usr/local/bin 目录下 9 | 10 | sudo mv phpunit-6.1.phar /usr/local/bin/phpunit 11 | 12 | - 在windows下。 13 | 14 | 新建一个phpunit.cmd 在该文件中输入 15 | 16 | @php "%~dp0phpunit-6.1.phar" %* 17 | 18 | 将phpunit.cmd所在的文件目录加入到环境变量之中,然后执行phpunit -version 检验一下是否成功。 19 | 20 | 21 | ### 使用composer 安装。 22 | 23 | composer require --dev phpunit/phpunit ^6.1 -------------------------------------------------------------------------------- /PHP/PHP手册笔记/0.php在unix平台安装.md: -------------------------------------------------------------------------------- 1 | 在unix平台下安装PHP的方法有 使用配置喝编译过程或者使用预编译的包。编译需要的知识和软件 2 | 3 | - 基础的 Unix 技能(有能力操作“make”和一种 C 语言编译器) 4 | - 一个 ANSI C 语言编译器 5 | - 一个 web 服务器 6 | - 任何模块特需的组件(例如 GD 和 PDF 库等) 7 | - autoconf: 2.13+(PHP < 5.4.0),2.59+(PHP >= 5.4.0) 8 | - automake: 1.4+ 9 | - libtool: 1.4.x+(除了 1.4.2) 10 | - re2c: 版本 0.13.4 或更高 11 | - flex: 版本 2.5.4(PHP <= 5.2) 12 | - bison: 版本 1.28(建议),1.35 或 1.75 13 | 14 | 15 | 16 | ## PHP和Apache的安装整合 17 | 18 | 以下只是简单安装,很多配置选项可以查到对应的文档 19 | 20 | apache文档 21 | 22 | [apache文档]: http://httpd.apache.org/docs/current/ -------------------------------------------------------------------------------- /PHP/PHP手册笔记/2-变量和常量.md: -------------------------------------------------------------------------------- 1 | ## 变量 2 | 3 | php中的变量是以 `$` 开头的。变量名区分大小写。合法的变量名是字母或者下划线开头,后面跟着任意数量的字母,数字,或者下划线 4 | 5 | 在此所说的字母是 a-z,A-Z,以及 ASCII 字符从 127 到 255(*0x7f-0xff*) 6 | 7 | 变量默认总是传值赋值 8 | 9 | ```php 10 | $a $_a $张三 // 合法的 11 | $2aaa //非法的 12 | $a = 123; 13 | ``` 14 | 15 | 16 | 17 | ### 变量的作用域 18 | 19 | 在最外层定义的是全局变量。在全局都有效。在函数内部的成为局部变量。只有函数内部可以访问。使用static修饰的变量,是静态变量。静态变量不会被销毁。只有等程序运行结束后才被回收. 20 | 21 | **$this 是一个特殊的变量。不能定位成this变量** 22 | 23 | ```php 24 | 47 | ``` 48 | 49 | 50 | 51 | 确定变量的类型。php提供了以下函数 52 | 53 | ```php 54 | gettype() is_bool() is_string() is_object() is_array(); 55 | ``` 56 | 57 | ## 常量 58 | 59 | 常量一般是定义之后不能再更改的变量。传统上使用大写字母来定义常量.合法的常量命名跟变量一致。只是不需要加 `$` 符号。 60 | 61 | ```php 62 | IS_DEBUG; 63 | define("IS_DEBUG",0); 64 | ``` 65 | 66 | #### 魔术常量 67 | 68 | 魔术常量是php内置的。可能跟着代码的变化而变化。一般魔术常量 以双下划线开始 双下划线结束。 69 | 70 | ```php 71 | __LINE__ 72 | __DIR__ 73 | __FILE__ 74 | __CLASS__ 75 | ``` 76 | 77 | 78 | 79 | ## 表达式 80 | 81 | 最精确的定义一个表达式的方式就是“任何有值的东西”。最简单的表达式。常量和变量。 82 | 83 | ```php 84 | $a; 85 | ;// 空表达式 86 | $a = 1;//赋值表达式 87 | 88 | function f(){} //函数表达式 89 | $a>1 //比较表达式 90 | 91 | ``` 92 | 93 | -------------------------------------------------------------------------------- /PHP/php7匿名类.md: -------------------------------------------------------------------------------- 1 | ## 匿名类 2 | 3 | > php7开始支持匿名类。可以 创建一次性对象。 4 | 5 | 在php7之前 6 | 7 | class User { 8 | public function getName() { 9 | return "name"; 10 | } 11 | } 12 | 13 | class X { 14 | public $ins; 15 | public function __construct( $user) { 16 | $this->_user = $user; 17 | 18 | } 19 | } 20 | $a = new User(); 21 | $x = new X($a); 22 | var_dump($x->ins->getName()); 23 | 24 | 25 | 在php7时候 26 | 27 | class X { 28 | public $_user; 29 | public function __construct($user) { 30 | $this->_user = $user; 31 | 32 | } 33 | } 34 | $a = new User(); 35 | $x = new X(new class {public function getName() {return "111";}}); 36 | var_dump($x->_user->getName()); 37 | 38 | > 匿名类被嵌套进普通 Class 后,不能访问这个外部类(Outer class)的 private(私有)、protected(受保护)方法或者属性。 为了访问外部类(Outer class)protected 属性或方法,匿名类可以 extend(扩展)此外部类。 为了使用外部类(Outer class)的 private 属性,必须通过构造器传进来: 39 | 40 | class Outer 41 | { 42 | private $prop = 1; 43 | protected $prop2 = 2; 44 | 45 | protected function func1() 46 | { 47 | return 3; 48 | } 49 | 50 | public function func2() 51 | { 52 | return new class($this->prop) extends Outer { 53 | private $prop3; 54 | 55 | public function __construct($prop) 56 | { 57 | $this->prop3 = $prop; 58 | } 59 | 60 | public function func3() 61 | { 62 | return $this->prop2 + $this->prop3 + $this->func1(); 63 | } 64 | }; 65 | } 66 | } 67 | 68 | echo (new Outer)->func2()->func3(); 69 | -------------------------------------------------------------------------------- /PHP/php动态添加拓展.md: -------------------------------------------------------------------------------- 1 | ## Linux PHP 动态添加拓展 2 | 3 | > 使用php的常见问题是编译php时忘记添加某扩展,后来想添加扩展,但是因为安装php后又装了一些东西如PEAR等,不想删除目录重装,这里就需要用到phpize了。 4 | 5 | > php 安装在/usr/local/php 目录下 6 | 7 | 以php7的源码包为例 php的源码目录里有一个**ext** 目录 就是拓展的目录 8 | 9 | cd ext #切换到ext目录 10 | 11 | ext目录里面有很多的拓展,比如curl openssl opcache 等。下面以opcache为例。 12 | 13 | cd opcache #进入到opcache目录 14 | 15 | 一般的拓展的目录里面都会有一个config.m4的文件 有些时候这个文件是config0.m4 你需要改成config.m4 16 | 17 | 18 | ### 编译opcache 拓展 使用phpize 19 | 20 | /usr/local/php/bin/phpize 21 | 22 | ./configure --with-php-config=/usr/local/php/bin/php-config 23 | 24 | make && make install 25 | 26 | 安装完毕之后会看到 Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-non-zts-20151012/ 27 | 28 | /usr/local/php/lib/php/extensions/no-debug-non-zts-20151012/就是编译好的拓展库的目录 会存在opcache.so 将该拓展加到php.ini即可 29 | 30 | vim php.ini 31 | 32 | 把 extension_dir 前面的;去掉 然后把=后面的值改成 **/usr/local/php/lib/php/extensions/no-debug-non-zts-20151012/** 33 | 34 | 在下一行中加入 **extension = opcache.so** 重启php 就能看到opcache拓展了 35 | 36 | 37 | php 有些拓展没有在源码包里 如memcache redis 等 可以去[http://pecl.php.net/](http://pecl.php.net/ "http://pecl.php.net/")下载 安装方法一样。 -------------------------------------------------------------------------------- /PHP/php识别条码.md: -------------------------------------------------------------------------------- 1 | ## 利用php识别条码 2 | 3 | >php 识别条形码拓展php-zbarcode 该拓展依赖ImageMagick和zbar 4 | 5 | 1. 安装ImageMagick依赖 6 | 7 | > yum install ImageMagick ImageMagick-devel 8 | 9 | 2. 安装zbar拓展 10 | 11 | > wget -c http://jaist.dl.sourceforge.net/project/zbar/zbar/0.10/zbar-0.10.tar.bz2 12 | > tar jxvf zbar-0.10.tar.bz2 13 | > cd zbar-0.10 14 | > ./configure --without-gtk --without-python --without-qt --prefix=/usr/local/zbar ##禁止gtk,python和qt的支持 15 | > make && make install 16 | 17 | 18 | 3. 安装php-zbarcode 19 | 20 | > git clone https://github.com/mkoppanen/php-zbarcode.git 21 | > cd php-zbarcode 22 | > /usr/local/php/bin/phpize #自己phpize的位置 23 | > ./configure --with-php-config=/usr/local/php/bin/php-config --with-zbarcode=/usr/local/zbar/ 24 | > make && make install 25 | 26 | 4. 添加extension=zbarcode.so 到php.ini中 然后重启apache 27 | 28 | ### 测试phpzbarcode的效果 29 | 30 | scan($image); 39 | 40 | //循环输出二维码信息 41 | if (!empty($barcode)) { 42 | foreach ($barcode as $code) { 43 | echo $code['type'];//图像的条码类型 44 | echo $code['data'];//条码的数据 45 | } 46 | } 47 | ?> 48 | 49 | 50 | -------------------------------------------------------------------------------- /PHP/swoole/1.swoole install.md: -------------------------------------------------------------------------------- 1 | ## swoole 编译安装 2 | > Swoole扩展是按照PHP标准扩展构建的。使用phpize来生成编译检测脚本,./configure来做编译配置检测,make进行编译,make install进行安装。 3 | 4 | 安装前的准备 5 | 6 | 1. php-5.3.10 或更高版本 7 | 2. gcc-4.4 或更高版本 8 | 3. make 9 | 4. autoconf 10 | 5. pcre 11 | 6. hiredis [非必须] 需要异步redis 则必须 12 | 7. nghttp2 【非必须】需要支持http2 则必须 13 | **ubutu用户可以使用** 14 | ```shell 15 | sudo apt install gcc make autoconf libpcre3 libpcre3-dev curl wget 16 | ``` 17 | **centos 用户可以使用** 18 | ```bash 19 | sudo yum -y install gcc make autoconf pcre pcre-devel curl wget 20 | ``` 21 | 准备hiredis 22 | 23 | ```shell 24 | $ wget -c https://github.com/redis/hiredis/archive/v0.13.3.zip 25 | $ tar zxvf v0.13.3.zip 26 | ``` 27 | 2 . nghttp 28 | 29 | ```shell 30 | $ wget -c https://github.com/nghttp2/nghttp2/releases/download/v1.32.0/nghttp2-1.32.0.tar.gz 31 | $ tar zxvf nghttp2-1.32.0.tar.gz 32 | $ cd nghttp2-1.32.0 33 | $ sudo ./configure && sudo make && sudo make install 34 | ``` 35 | ### 编译swoole 36 | ```shell 37 | $ wget -c https://github.com/swoole/swoole-src/archive/master.tar.gz 38 | $ tar zxvf master.tar.gz 39 | $ cd swoole-src-master 40 | $ /usr/local/php/bin/phpize 41 | $ ./congiure --with-php-config=/usr/local/php/bin/php-config \ 42 | --enable-openssl \ 43 | --enable-http2 \ 44 | --enable-async-redis=/root/hiredis \ #刚解压的hiredis的路径 45 | --enable-sockets \ 46 | 47 | $ sudo make && sudo make install 48 | ``` 49 | 加入php.ini 可以使用php --ini 找到对应的php.ini的位置。 然后在文件里面指定下swoole.so的路径 50 | extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20170718/swoole.so 51 | 检测swoole 52 | ``` 53 | php -m | grep swoole 54 | ``` 55 | -------------------------------------------------------------------------------- /PHP/swoole/Memory.md: -------------------------------------------------------------------------------- 1 | ## 内存操作 2 | 3 | Swoole提供了`7`个内存操作的模块。 4 | 5 | - lock 锁 6 | - buffer 缓冲 7 | - table 表 8 | - automic 原子计数器 9 | - mmap 磁盘映射 10 | - channel 队列 11 | - serialize 序列化 12 | 13 | 14 | 15 | ### table 16 | 17 | swoole_table 其实很简单,我们理解成一个hashtable 就行了。通过索引到对应的数据。我们需要定义这个表的大小。然后往里面进行增删改查 18 | 19 | #### 1. 初始化表 20 | 21 | `$size` 默认是1024,如果设置的值大于1024,而不是2的N次方,系统会调整成2的N的次方 22 | 23 | `$conflict_proportion` 表示hash冲突率。我们知道,hashtable 肯定会产生冲突,产生冲突空间就会增加。所以多预留了20%的空间作为冲突使用。 24 | 25 | ```php 26 | use Swoole\Table; 27 | $table = new Table($size = 1024,$conflict_proportion = 0.2); 28 | ``` 29 | 30 | ### 2. 设置表结构 column($key,$type) 31 | 32 | 定义表结构,就相当于我们创建数据库表的时候,需要指定哪些字段,这样我们插入数据,字段才能对应。 33 | 34 | ```php 35 | use Swoole\Table; 36 | $table->column('id',Table::TYPE_INT, 1); 37 | $table->column('name',Table::TYPE_STRING, 10); 38 | ``` 39 | 40 | ### 3. 创建表 create() 41 | 42 | 初始化和设置完表结构之后,我们就可以创建表了。 43 | 44 | ```php 45 | $table->create(); 46 | ``` 47 | 48 | ### 4. 添加数据set($key,array $data) 49 | 50 | 第一个参数是key,就是hash的key。我们通过这个key,找到底下的数组数据。相同的key,会覆盖数据、 51 | 52 | ```php 53 | $table->set('zhang',['id'=>1,'name'=>'zhangsan']); 54 | ``` 55 | 56 | ### 5. 读取数据 get($key) 57 | 58 | ``` 59 | array swoole_table->get(string $key, string $field = null); 60 | ``` 61 | 62 | ```php 63 | $data = $table->get("zhang"); 64 | echo $data['id']; 65 | ``` 66 | 67 | ### 6. 修改数据 68 | 69 | 修改数据是通过覆盖数据来实现的。 70 | 71 | ```php 72 | $table->set("zhang",["id"=>2]); 73 | ``` 74 | 75 | ### 7. 删除数据 del($key) 76 | 77 | ``` 78 | swoole_table->exist(string $key); 79 | ``` 80 | 81 | ```php 82 | $res = $table->del("zhang"); 83 | ``` 84 | 85 | ### 8. 获取表元素个数 count() 86 | 87 | ```php 88 | $number = $table->count(); 89 | ``` 90 | 91 | -------------------------------------------------------------------------------- /PHP/swoole/code/channel.php: -------------------------------------------------------------------------------- 1 | push($i); 7 | } 8 | var_dump($chan->stats()); 9 | while($data = $chan->pop()) { 10 | echo $data."\n"; 11 | } 12 | -------------------------------------------------------------------------------- /PHP/swoole/code/client.php: -------------------------------------------------------------------------------- 1 | on("connect", function(swoole_client $cli) { 5 | $cli->send("GET / HTTP/1.1\r\n\r\n"); 6 | }); 7 | $client->on("receive", function(swoole_client $cli, $data){ 8 | echo "Receive: $data"; 9 | $cli->send(str_repeat('A', 100)."\n"); 10 | }); 11 | $client->on("error", function(swoole_client $cli){ 12 | echo "error\n"; 13 | }); 14 | $client->on("close", function(swoole_client $cli){ 15 | echo "Connection close\n"; 16 | }); 17 | $client->connect('127.0.0.1', 9090); -------------------------------------------------------------------------------- /PHP/swoole/code/clientServer.php: -------------------------------------------------------------------------------- 1 | on("receive",function( $server, $fd, $reactor_id, $data) { 4 | $this->table->set(rand(2,10), ['id' => rand(2,10), 'name' => 'test2', 'age' => rand(10,30)]); 5 | }); 6 | $server->on("WorkerStart",function($server, int $worker_id){ 7 | swoole_set_process_name("php:tcp-server"); 8 | }); 9 | $server->start(); -------------------------------------------------------------------------------- /PHP/swoole/code/exec.php: -------------------------------------------------------------------------------- 1 | exec("/usr/bin/php",["-v"]); 5 | $worker->exit(0); 6 | },false,false); 7 | $process->start(); -------------------------------------------------------------------------------- /PHP/swoole/code/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 23 | 24 | -------------------------------------------------------------------------------- /PHP/swoole/code/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 首页 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /PHP/swoole/code/pipe.php: -------------------------------------------------------------------------------- 1 | write("我是子进程"); 8 | echo "heoo"; 9 | } 10 | 11 | $process = new Process('sonCallback',true); 12 | 13 | 14 | $process->start(); 15 | 16 | echo "读取子进程数据:".$process->read(); -------------------------------------------------------------------------------- /PHP/swoole/code/queue.php: -------------------------------------------------------------------------------- 1 | push('我来自于子进程'."数据{$i}"); 9 | } 10 | 11 | # code... 12 | } 13 | $process = new Process("sonFun",false,false);//关闭管道 14 | 15 | $process->useQueue(); 16 | 17 | $process->start(); 18 | 19 | echo "读取son进程数据:". $process->pop(); 20 | 21 | var_dump($process->statQueue()); -------------------------------------------------------------------------------- /PHP/swoole/code/table.php: -------------------------------------------------------------------------------- 1 | column('id',Table::TYPE_INT, 1); 8 | $table->column('name',Table::TYPE_STRING, 10); 9 | 10 | //创建表 11 | $table->create(); 12 | 13 | //添加数据 14 | 15 | $key = "zhang"; 16 | $data = ['id'=>1,"name"=>'tian']; 17 | $table->set($key ,$data); 18 | 19 | //读取表数据 20 | 21 | $name = $table->get($key ,'name'); 22 | echo $name."\n"; 23 | 24 | //修改表数据 25 | 26 | $table->set($key ,['name'=>'wang']); 27 | 28 | $new_name = $table->get($key ,'name'); 29 | echo $new_name."\n"; 30 | 31 | //删除字段 32 | 33 | $table->del($key); -------------------------------------------------------------------------------- /PHP/swoole/code/test.log: -------------------------------------------------------------------------------- 1 | [2018-08-19 16:40:46 @5488.0] WARNING swSocket_bind (ERROR 502): bind(0.0.0.0:9501) failed. Error: Address already in use [98] 2 | 5488退出了 -------------------------------------------------------------------------------- /PHP/swoole/images/938551899.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/PHP/swoole/images/938551899.gif -------------------------------------------------------------------------------- /PHP/swoole/images/93855347.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/PHP/swoole/images/93855347.gif -------------------------------------------------------------------------------- /PHP/深入了解php/第一章(从SAPI开始).md: -------------------------------------------------------------------------------- 1 | ## SAPI 2 | 3 | SAPI(server application program interface)服务应用接口 4 | 5 | SAPI就是PHP和外部环境的代理器。它把外部环境抽象后, 为内部的PHP提供一套固定的, 统一的接口, 使得PHP自身实现能够不受错综复杂的外部环境影响,保持一定的独立性 6 | 7 | ![image](http://laruence-wordpress.stor.sinaapp.com/uploads/php-arch.jpg) -------------------------------------------------------------------------------- /Python/Centos安装Python3.md: -------------------------------------------------------------------------------- 1 | ## centos 7 安装python3 2 | 3 | 因为centos内置了python,是古老的python2.7,这个python不能删掉,也不能替换,很多东西依赖这个python。我们安装python3 只能通过别名的方式 4 | 5 | ###1. 安装依赖包 6 | 7 | ```bash 8 | yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel 9 | 10 | ``` 11 | 12 | 13 | 14 | ### 2.源码编译安装 15 | 16 | ```bash 17 | wget https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tar.xz 18 | tar -xvJf Python-3.6.2.tar.xz 19 | cd Python-3.6.2 20 | ./configure --prefix=/usr/local/python3 21 | make && make install 22 | 23 | ``` 24 | 25 | ###3. 创建软链接 26 | 27 | ```bash 28 | ln -s /usr/local/python3/bin/python3 /usr/bin/python3 29 | ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3 30 | ``` 31 | 32 | -------------------------------------------------------------------------------- /Python/Python 数据结构.md: -------------------------------------------------------------------------------- 1 | ## more lists 2 | 3 | - list.append 4 | 5 | 添加一个元素到list中 6 | 7 | - list.extend(iterable) 8 | 9 | list转成迭代器 10 | 11 | - list.insert(i, x) 12 | 13 | 插入一个元素 14 | 15 | - list.remove(x) 16 | 17 | 移动一个元素 18 | 19 | - list.pop([i]) 20 | 21 | 出栈 22 | 23 | - list.clear() 24 | 25 | 清空list 26 | 27 | - list.count(x) 28 | 29 | 返回列表中x元素出现的次数 30 | 31 | - list.sort(key=None, reverse=False) 32 | 33 | 列表排序 34 | 35 | - list.reverse() 36 | 37 | 列表反转 38 | 39 | - list.copy() 40 | 41 | 复制一个列表 42 | 43 | 44 | lists = ['a','b','c','d','e'] 45 | 46 | lists.append('f') 47 | 48 | # 插入到第6位 49 | lists.insert(6,'g') 50 | 51 | lists.remove('e') 52 | 53 | print(lists.pop()) 54 | 55 | print(lists.count('a')) 56 | 57 | lists.sort() 58 | 59 | ## 使用lists 作为栈 60 | 61 | 栈先进后出 62 | 63 | lists.append('h') 64 | 65 | lists.append('i') 66 | 67 | print(lists.pop()) # i 68 | 69 | 70 | ## 使用lists作队列 71 | 72 | 队列 先进先出 73 | 74 | from collections import deque 75 | 76 | queue = deque([]) 77 | 78 | queue.append('a') 79 | 80 | queue.append('b') 81 | 82 | print(queue.popleft()) 83 | 84 | 85 | 86 | ## set 集合 87 | 88 | 89 | 集合是不允许重复的数据 90 | 91 | sets = {1,3,'a','b'} -------------------------------------------------------------------------------- /Python/Python(Package).md: -------------------------------------------------------------------------------- 1 | ## python 包 2 | 3 | 在python种一个单独的文件成为模块,模块中可以包含多个函数、类等。多个模块组成了一个包。 4 | 5 | 可以作为模块的文件类型有**.py、.pyo、.pyc、.pyd、.so、.dll** 6 | 7 | ``` 8 | package 9 | |- subpackage1 10 | |- __init__.py 11 | |- a.py 12 | |- subpackage2 13 | |- __init__.py 14 | |- b.py 15 | ``` 16 | 17 | ### 导入 18 | 19 | ```python 20 | import subpackage1.a # 将模块subpackage.a导入全局命名空间,例如访问a中属性时用subpackage1.a.attr 21 | from subpackage1 import a # 将模块a导入全局命名空间,例如访问a中属性时用a.attr_a 22 | from subpackage.a import attr_a # 将模块a的属性直接导入到命名空间中,例如访问a中属性时直接用attr_a 23 | ``` 24 | 25 | ### ` __init__` 26 | 27 | `__init__.py `文件的作用是将文件夹变为一个Python模块,Python 中的每个模块的包中,都有`__init__.py` 文件。 28 | 29 | 通常`__init__.py` 文件为空,但是我们还可以为它增加其他的功能。我们在导入一个包时,实际上是导入了它的`__init__.py`文件。这样我们可以在`__init__.py`文件中批量导入我们所需要的模块,而不再需要一个一个的导入。 30 | 31 | ```python 32 | #__init__.py 33 | # package 34 | import re 35 | import urllib 36 | import sys 37 | import os 38 | 39 | # a.py 40 | import package.re 41 | ``` 42 | 43 | `__init__.py`中还有一个重要的变量,`__all_`_, 它用来将模块全部导入。 44 | 45 | ```python 46 | # __init__.py 47 | __all__ = ['os', 'sys', 're', 'urllib'] 48 | 49 | # a.py 50 | from package import * 51 | ``` 52 | 53 | 这时就会把注册在`__init__.py`文件中`__all__`列表中的模块和包导入到当前文件中来。 54 | 55 | ### import语句引用机制 56 | 57 | 可以被import语句导入的对象是以下类型: 58 | 59 | - 模块文件(.py文件) 60 | - C或C++扩展(已编译为共享库或DLL文件) 61 | - 包(包含多个模块) 62 | - 内建模块(使用C编写并已链接到Python解释器中) 63 | 64 | 导入模块的时候,解释器会按照**sys.path**列表中的目录顺序来查找导入文件 -------------------------------------------------------------------------------- /Python/Python-函数.md: -------------------------------------------------------------------------------- 1 | ## 函数 2 | 3 | > python 的函数的定义实用df定义 4 | 5 | df fn(): 6 | print('11') 7 | 8 | ### 函数的参数 9 | 10 | - 位置参数 11 | 12 | def fn(a): 13 | print(a) 14 | fn(1) 15 | 16 | 17 | - 默认参数 18 | 19 | > 当参数不传递的时候,使用默认值.必选参数要放到前面。 20 | 21 | def fn(a=1): 22 | print(a) 23 | fn() 24 | 25 | - 可变参数 26 | 27 | 28 | > 函数的参数的是变化的。不固定 接收到的是一个tuple 29 | 30 | def fn(*num): 31 | for i in num: 32 | print(i) 33 | 34 | fn(1,2,3,5) 35 | 36 | 37 | - 命名关键字参数 38 | 39 | def fn(name='',age='',addree=''): 40 | fn(age=15) -------------------------------------------------------------------------------- /Python/Python-数据类型.md: -------------------------------------------------------------------------------- 1 | ## 数据类型 2 | 3 | > python提供了数据类型有整型、浮点型、字符串、布尔、空值、字典、列表 4 | 5 | 6 | - **整型** 7 | 8 | > 整型就是整数,包括正整数和负整数。十六进制的整数用前面加上ox 9 | 10 | - **浮点数** 11 | 12 | > 浮点型也就是小数 如0.1 1.25 13 | 14 | - **字符串** 15 | 16 | > python 字符串以单引号或双引号括起来的字字符。如'abc' "abc" 17 | 18 | - **布尔** 19 | 20 | > python中的布尔类型 **True** 表示真 **False** 表示假 **首字母大写。** 21 | 22 | - **列表list** 23 | 24 | > list是一个有序的数据的集合,可以进行增删改查、 25 | 26 | list1 =['a','b'] 27 | print(list1[1]) 28 | list1.append('c')//追加一个元素 29 | list1.insert(1,'d')//添加到指定的位置 30 | list1.pop()//删除末尾的元素 31 | 32 | - **元祖tuple** 33 | 34 | > 也是一种有序列表。一旦定义了之后就不能修改。所以没有append和insert的方法 35 | 36 | tup = (1,2,3) 37 | 38 | - **字典dict** 39 | 40 | > 键值存储的key=>value的格式 41 | 42 | dict1 = ['a','b'] 43 | dict2 = {"name":"jack","age":18} 44 | dist2.pop(name) //删除key为name的元素 45 | dist2['name']//取值 46 | dist2.get('name') 47 | 48 | - **set** 49 | 50 | > set 和dist类似。是一个key的集合。但是不存储value,key不重复、 51 | 52 | s = set([2,5,7]) 53 | s.add(3) 54 | s.remove(2) 55 | 56 | ### list相关操作 57 | 58 | - 切片(取出list中部分元素) 59 | 60 | list1 = ['1','a',3] 61 | list1[0] //取出第一个元素 62 | list1[0:2]//取出前两个元素 0索引开始到2为止 63 | list1[-1]//取出最后一个元素 64 | list1[::2]//间隔取值 65 | 66 | -------------------------------------------------------------------------------- /Python/Python标准库.md: -------------------------------------------------------------------------------- 1 | ## 操作系统接口 2 | 3 | - os模块封装了操作系统的常用接口 4 | 5 | - shutil提供了文件操作的接口 6 | 7 | 8 | >>> import shutil 9 | >>> shutil.copyfile('data.db', 'archive.db') 10 | 'archive.db' 11 | >>> shutil.move('/build/executables', 'installdir') 12 | 13 | 14 | - glob 模块提供了文件搜索的函数 15 | 16 | 17 | print(glob.glob('*.py')) 18 | 19 | - sys 提供命令行参数 20 | 21 | 22 | import sys 23 | print(sys.argv) 24 | 25 | - re模块提供了正则表达式相关的接口 26 | 27 | 28 | re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest') 29 | 30 | - math 模块提供了数学相关的接口 31 | 32 | 33 | 34 | - 网络接口 Internet Access urllib.request 35 | 36 | 37 | - datetime 提供了时间和日期相关的接口 38 | 39 | print(datetime.date.today()) 40 | 41 | -------------------------------------------------------------------------------- /Python/Python模块和包.md: -------------------------------------------------------------------------------- 1 | ## Modules 模块 2 | 3 | 4 | 一个python文件就是一个模块。模块的名字就是文件的名字。模块的名字可以用全局的变量 __name__ 5 | 6 | import lists 7 | 8 | lists.stacks() 9 | 10 | print(lists.__name__);//lists 11 | 12 | 模块的搜索 13 | 14 | 1. 当前目录的文件 15 | 2. PYTHONPATH配置的目录 16 | 3. 安装的默认的目录 17 | 18 | 编译python模块的时候 会生成一个__pycache__ 目录。 19 | 20 | ### dir 函数 21 | 22 | 查看模块有哪些定义的变量和函数。 23 | 24 | 25 | ## 包 26 | 27 | 28 | sound/ 顶级包目录 29 | __init__.py 初始化sound package 30 | formats/ 子包文件 31 | __init__.py 32 | wavread.py 33 | wavwrite.py 34 | aiffread.py 35 | aiffwrite.py 36 | auread.py 37 | auwrite.py 38 | ... 39 | effects/ Subpackage for sound -------------------------------------------------------------------------------- /Python/Python错误和异常.md: -------------------------------------------------------------------------------- 1 | ## 错误和异常 2 | 3 | 捕获异常 4 | 5 | 6 | try: 7 | x = int(input("Please enter a number: ")) 8 | break 9 | except ValueError: 10 | print("Oops! That was no valid number. Try again...") -------------------------------------------------------------------------------- /Python/Python面向对象.md: -------------------------------------------------------------------------------- 1 | ## 面向对象 2 | 3 | 定义一个类 4 | 5 | 6 | class New(): 7 | name = 'xhang' 8 | """构造函数""" 9 | def __init__(self): 10 | 11 | pass; 12 | 13 | def test(self): 14 | print(self.name) 15 | 16 | 17 | n = New() 18 | n.test() 19 | 20 | ### 继承 21 | 22 | 继承的实现 定义的时候在括号中传入父类的名字 23 | 24 | class New1(New): 25 | """docstring for New""" 26 | def __init__(self): 27 | super(New, self).__init__()#继承父类的构造 28 | self.test() 29 | 30 | new1 = New1() 31 | 32 | ### 多继承 33 | 34 | new3 集成了New1 Test 35 | ``` 36 | class New3(New1,Test): 37 | def __init__(self): 38 | self.test() 39 | self.test1() 40 | 41 | ``` 42 | ### 私有属性和方法 43 | 44 | 双下划线定义的属性 45 | 46 | __user 47 | ### 魔术方法 48 | 49 | __init__ : 构造函数,在生成对象时调用 50 | __del__ : 析构函数,释放对象时使用 51 | __repr__ : 打印,转换 52 | __setitem__ : 按照索引赋值 53 | __getitem__: 按照索引获取值 54 | __len__: 获得长度 55 | __cmp__: 比较运算 56 | __call__: 函数调用 57 | __add__: 加运算 58 | __sub__: 减运算 59 | __mul__: 乘运算 60 | __div__: 除运算 61 | __mod__: 求余运算 62 | __pow__: 称方 -------------------------------------------------------------------------------- /Python/itertools.md: -------------------------------------------------------------------------------- 1 | Python的内建模块itertools提供了非常有用的用于操作迭代对象的函数。 2 | 3 | 今天我有一个朋友问我。有三个集合 a [1,3,4] b [2,5,6] c[6,1,3] 怎么得到他们的所有的集合。最初的时候,想到用for,但是需要三次,感觉不优雅。后来查到python 4 | 内置了itertools 可以很方便的计算排列组合。上面的需求就是笛卡尔积 5 | 6 | ```python 7 | import itertools 8 | list(itertools.product(a,b,c)) 9 | ``` 10 | -------------------------------------------------------------------------------- /Python/php生成器和迭代.md: -------------------------------------------------------------------------------- 1 | ## 2 | 3 | 生成器对象Generator 继承Iterator 4 | Generator 对象不能通过 new 实例化.必须通过子类去实现。 5 | 迭代器需要实现的方法: 6 | 7 | - Generator::current — 返回当前产生的值 8 | - Generator::key — 返回当前产生的键 9 | - Generator::next — 生成器继续执行 10 | - Generator::rewind — 重置迭代器 11 | - Generator::valid — 检查迭代器是否被关闭 12 | 13 | 14 | ## yeild 关键字 15 | 16 | > yield 与 return 相似,不同的是 yield 不会终止函数的执行,而是为循环提供一个值并暂停生成器函数的执行 17 | 18 | foreach(range(1,100) as $k=>$v){ 19 | 20 | echo $v; 21 | } 22 | 23 | function xrange($start,$end){ 24 | for($i=$start;$i<$end;$i++){ 25 | yeild $i; 26 | } 27 | } 28 | 29 | foreach(xrange(1,1000) as $v){ 30 | 31 | echo $v; 32 | } 33 | 34 | 35 | send 36 | 37 | 向生成器中传入一个值,并且当做 yield 表达式的结果,然后继续执行生成器。 -------------------------------------------------------------------------------- /Python/python(文件读写).md: -------------------------------------------------------------------------------- 1 | ## python file 2 | 3 | - 读取文件 4 | 5 | ``` 6 | fp = open(filename,'w+',encoding='utf-8') 7 | fp.read() 8 | ``` 9 | 10 | - 写入文件 11 | 12 | ``` 13 | fp.write(data) 14 | 15 | ``` 16 | 17 | ``` 18 | 19 | with open(filename) as fp: 20 | fp.read() 21 | fp.close() 22 | ``` -------------------------------------------------------------------------------- /Python/python(shutil 模块).md: -------------------------------------------------------------------------------- 1 | ## shutil 模块 2 | 3 | - shutil.copyfile( src, dst) 4 | 5 | 从源src复制到dst中去。当然前提是目标地址是具备可写权限。抛出的异常信息为IOException. 如果当前的dst已存在的话就会被覆盖掉 6 | 7 | - shutil.move( src, dst) 移动文件或重命名 8 | 9 | - shutil.copymode( src, dst) 10 | 11 | 只是会复制其权限其他的东西是不会被复制的 12 | 13 | - shutil.copystat( src, dst) 复制权限、最后访问时间、最后修改时间 14 | 15 | - shutil.copy( src, dst) 复制一个文件到一个文件或一个目录 16 | 17 | - shutil.copy2( src, dst) 18 | 19 | 在copy上的基础上再复制文件最后访问时间与修改时间也复制过来了,类似于cp –p的东西 20 | 21 | - shutil.copy2( src, dst) 22 | 23 | 如果两个位置的文件系统是一样的话相当于是rename操作,只是改名;如果是不在相同的文件系统的话就是做move操作 24 | 25 | - shutil.copytree( olddir, newdir, True/Flase) 26 | 27 | 把olddir拷贝一份newdir,如果第3个参数是True,则复制目录时将保持文件夹下的符号连接,如果第3个参数是False,则将在复制的目录下生成物理副本来替代符号连接 28 | 29 | - shutil.rmtree( src ) 递归删除一个目录以及目录内的所有内容 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 这里是自己学习过程中记录的笔记。如有错误,欢迎指出。 -------------------------------------------------------------------------------- /docker/2.docker 基本操作.md: -------------------------------------------------------------------------------- 1 | ## docker 基本操作 2 | 3 | 1. 查看运行的容器 4 | 5 | ```shell 6 | docker ps 7 | ``` 8 | 9 | 2. 停止容器 10 | 11 | ```bash 12 | docker stop container-id 13 | ``` 14 | 15 | 3. 启动容器 16 | 17 | ``` 18 | docker run xx/xx 19 | ``` 20 | 21 | 4. 进去容器 22 | 23 | ```bash 24 | docker exec -it [CONTAINER-ID] /bin/sh 25 | ``` 26 | 27 | 5. 退出容器 28 | 29 | ```bash 30 | exit 31 | ``` 32 | 33 | ### docker 端口和本地宿主机器端口映射 34 | 35 | 假设容器的名字叫ubuntu 36 | 37 | 1. 对容器暴露所有的端口,随机映射宿主机端口 38 | 39 | ```bash 40 | docker run -P -it ubuntu /bin/bash 41 | ``` 42 | 43 | 2. 映射宿主机随机端口到容器指定的端口 44 | 45 | ```bash 46 | docker run -p 80 -it ubuntu /bin/bash 47 | ``` 48 | 49 | 3. 映射宿主机的指定端口到容器指定端口 1对1 50 | 51 | ```bash 52 | docker run -p 8080:8080 -it ubuntu /bin/bash 53 | ``` 54 | 55 | 4. 指定容器ip和容器端口,宿主机端口随机映射 56 | 57 | ```bash 58 | docker run -p 127.0.0.1::80 -it ubuntu /bin/bash 59 | ``` 60 | -------------------------------------------------------------------------------- /docker/install.sh: -------------------------------------------------------------------------------- 1 | # !/bin/bash 2 | 3 | sudo apt-get -y autoremove docker docker-engine docker.io 4 | sudo apt-get update 5 | curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add - 6 | sudo apt-key fingerprint 0EBFCD88 7 | 8 | sudo add-apt-repository \ 9 | "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu \ 10 | $(lsb_release -cs) \ 11 | stable" 12 | 13 | sudo apt-get update 14 | sudo apt-get install docker-ce 15 | 16 | sudo groupadd docker 17 | sudo gpasswd -a ${USER} docker 18 | 19 | sudo su 20 | echo '{"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn/"]}' > /etc/docker/daemon.json 21 | sudo service docker restart 22 | newgrp - docker 23 | exit 24 | -------------------------------------------------------------------------------- /git/Git来管控CRLF和LF混乱局面.md: -------------------------------------------------------------------------------- 1 | ## 一、背景 2 | 在各操作系统下,文本文件所使用的换行符是不一样的。UNIX/Linux 使用的是 0x0A(LF),早期的 Mac OS 使用的是0x0D(CR), 3 | 后来的 OS X 在更换内核后与 UNIX 保持一致了。但 DOS/Windows 一直使用 0x0D0A(CRLF)作为换行符。 4 | Git提供了一个“换行符自动转换”功能。这个功能默认处于“自动模式”,当你在签出文件时,它试图将 UNIX 换行符(LF)替换为 Windows 的换行符(CRLF); 5 | 当你在提交文件时,它又试图将 CRLF 替换为 LF。Git 的“换行符自动转换”功能听起来似乎很智能、很贴心,因为它试图一方面保持仓库内文件的一致性(UNIX 风格), 6 | 一方面又保证本地文件的兼容性(Windows 风格)。但遗憾的是,这个功能是有 bug 的,而且在短期内都不太可能会修正 7 | 8 | ## git设置 9 | 10 | ```bash 11 | git config --global core.autocrlf false 12 | git config --global core.safecrlf true 13 | 含义: 14 | AutoCRLF 15 | #提交时转换为LF,检出时转换为CRLF 16 | git config --global core.autocrlf true 17 | 18 | #提交时转换为LF,检出时不转换 19 | git config --global core.autocrlf input 20 | 21 | #提交检出均不转换 22 | git config --global core.autocrlf false 23 | SafeCRLF 24 | #拒绝提交包含混合换行符的文件 25 | git config --global core.safecrlf true 26 | 27 | #允许提交包含混合换行符的文件 28 | git config --global core.safecrlf false 29 | 30 | #提交包含混合换行符的文件时给出警告 31 | git config --global core.safecrlf warn 32 | ``` 33 | -------------------------------------------------------------------------------- /git/git checkout.md: -------------------------------------------------------------------------------- 1 | ## git checkout 2 | 3 | git checkout 的常用功能:检出分支和检出文件 4 | 5 | - 切换分支 `git checkout -b | B pointStart` 6 | 7 | ```shell 8 | git checkout -b dev master # 以master为基础创建并切换到一个新的分支dev 9 | git checkout -b dev f7742cd #以commitid为基础创建一个新的分支 10 | ``` 11 | 12 | - 检出文件 `git checkout -- [filename]` 13 | 14 | 有时我们会错删了文件。这个时候,就需要使用重新检出。 15 | 16 | ```shell 17 | git checkout -- filename 18 | git checkout -- "*.c" 19 | ``` 20 | 21 | - 从别的分支检出文件 `git checkout [branch] -- [file name]` 22 | 23 | 比如我们有两个分支A和B、A分支需要用到B的文件。这个时候,我们就可以用checkout 24 | 25 | 比如 b分支 config.php 。我们需要把这个分支的文件加到自己的分支中。 26 | 27 | ```shell 28 | git checkout B config.php #把B分支的文件检出到当前分支 29 | ``` 30 | 31 | 32 | -------------------------------------------------------------------------------- /git/git log.md: -------------------------------------------------------------------------------- 1 | ## git log 2 | 3 | 查看git log 能帮助我们很清晰的了解过去的改动,帮助我们回滚代码 4 | 5 | ```bash 6 | git log 7 | #查看对应文件的改动 8 | git log -p app.js 9 | ``` 10 | ## git blame 11 | 12 | 场景:查看每一行代码的最后改动时间,以及提交人。例如,追溯app.js文件中某一行是被谁改坏的。 13 | 步骤:通过 `git blame` 来查询。 14 | ``` 15 | git blame app.js 16 | ``` 17 | -------------------------------------------------------------------------------- /git/worktree.md: -------------------------------------------------------------------------------- 1 | ## git worktree 2 | 3 | 今天用学会了一个很有用的命令。`git worktree` 4 | 5 | git worktree 从一个仓库中可以创建多个工作目录,方便多开编辑器并行开发。 6 | 7 | 场景介绍: 8 | 9 | 你正在feature分支上,进行开发工作,但是突然线上有个bug,需要你立即修复下,但是你的feature工作还没有完成,一般我们的正常的做法,有两种 10 | 11 | - `git stash` 保存暂存区 12 | 13 | ```bash 14 | git stash 15 | 16 | git co master && git pull --rebase && git checkout -b hotfix 17 | .... 18 | 19 | git checkout feature 20 | git stash pop 21 | ``` 22 | 23 | - `git reset` 先保存 后恢复 24 | 25 | ```bash 26 | git add . && git commit -m 'test' 27 | git co master && git pull --rebase && git checkout -b hotfix 28 | ....修复bug 29 | git checkout feature 30 | git reset 31 | ``` 32 | 33 | 但是这个时候,会有一个问题。就是如果线上的代码依赖,如果和你的feature不一致,你需要更新的你的依赖,同时又会导致你的feature的依赖出问题。举个例子 34 | 35 | 比如你的线上的依赖redis:1.4版本。但是你的feature版本是在1.5版本的。这个时候你需要把你的版本来回的变动。 36 | 37 | 第二种情况。如果你的feature分支,正在进行的是编译或者其他的跑测试的功能,这个时候,你不能切换分支,一旦你切换了工作目录。就会导致脚本停止了。为了解决上面的两个问题。`git worktree` 就有用了 38 | 39 | **`git worktree add -b <新分支名> <新路径> <从此分支创建> `** 40 | 41 | ```bash 42 | git worktree add -b hotfix ../hotfix master 43 | ``` 44 | 45 | 这个时候 当前工作目录上级就会出现一个hotfix的目录。你进到该目录。就是一个新的分支。这个工作 目录你的feature 都是一个独立的分支。你可以在该目录下继续干活。又不会影响你的feature的分支。然后干完活之后,就可以把这个记录给干掉了。 46 | 47 | 如果要删除其中一个工作目录,直接删除文件夹即可。随后使用命令清除多余的已经被删的工作目录: 48 | 49 | ```bash 50 | git worktree prune 51 | ``` 52 | 53 | 相比于克隆多个仓库,使用这种方法创建的多个目录,有诸多好处: 54 | 55 | - 只有一个仓库会占用版本库的空间,其它只占用工作目录的空间,对大型项目而言非常节省空间。 56 | - 因为所有工作目录共享一个仓库,所以一个更新意味着整个更新(A 目录里对分支做的改动,B 目录里切到此分支也是改动后的;避免到时候找不到某个未推送的改动改到了哪个仓库) 57 | -------------------------------------------------------------------------------- /git忽略文件.md: -------------------------------------------------------------------------------- 1 | ## git rm与git rm --cached 2 | 3 | 有些时候,我们在开发过程中。不需要加到代码库中。比如写了一些test等等。但是又不是gitignore的内容。我们需要使用git rm --cached git会自动把该文件加到`.gitignore`中 如果想恢复,需要把`.gitignore`中的该文件去掉即可 4 | 5 | 6 | 当我们需要删除暂存区或分支上的文件, 同时工作区也不需要这个文件了, 可以使用 7 | ```bash 8 | git rm filename 9 | ``` 10 | 当我们需要删除暂存区或分支上的文件, 但本地又需要使用, 只是不希望这个文件被版本控制, 可以使用 11 | 12 | 13 | ```bash 14 | git rm --cached filename 15 | ``` 16 | ## 全局ingore 17 | 有些时候,我们需要全局设置,不是需要对每个项目进行单独的设置,可以通过以下步骤 18 | 19 | ```bash 20 | cd ~ 21 | touch .gitignore_global 22 | git config --global core.excludesfile ~/.gitignore_global 23 | ``` 24 | 然后在`.gitignore_global` 中 加入自己想忽略的文件即可。如 25 | 26 | ``` 27 | node_modules/ 28 | config.js 29 | config.php 30 | vendor/ 31 | ``` 32 | -------------------------------------------------------------------------------- /go/Map & struct.md: -------------------------------------------------------------------------------- 1 | ## Map 2 | 3 | Map是使用散列表来实现,就是我们常说的Hash表,所以我们每次迭代Map的时候,打印的Key和Value是无序的,每次迭代的都不一样,即使我们按照一定的顺序存在也不行。 4 | 5 | > **Map存储的是无序的键值对集合** 6 | 7 | ### 声明和初始化 8 | 9 | ```var dict map[string]intgo 10 | var dict map[string]int 11 | dist := make(map[string]int) 12 | ``` 13 | 14 | 字面量赋值 15 | 16 | ```go 17 | dict := map[string]int{"张三":43} 18 | ``` 19 | 20 | Map的键可以是任何值,键的类型可以是内置的类型,也可以是结构类型 21 | 22 | ### 使用map 23 | 24 | ```go 25 | fmt.Println(dict["张三"]) 26 | delete(dict,"张三")//删除键值 27 | //遍历 28 | for k,v := range dict { 29 | fmt.Println(k,v) 30 | } 31 | ``` 32 | 33 | > map是引用类型的,在函数之间传递,修改map会改变map的值 34 | 35 | ## 类型 36 | 37 | Go 语言是一种静态类型的编程语言,所以在编译器进行编译的时候,就要知道每个值的类型,这样编译器就知道要为这个值分配多少内存,并且知道这段分配的内存表示什么。 38 | 39 | ### 基本类型 40 | 41 | 基本类型是内置的类型。比如数值类型、浮点类型、字符类型以及布尔类型,他们本质上是原始类型 。进行函数参数传递 都是传的值拷贝。 42 | 43 | ### 引用类型 44 | 45 | 引用类型和原始的基本类型恰恰相反,它的修改可以影响到任何引用到它的变量。在Go语言中,引用类型有**切片**、**map**、**接口**、**函数类型**以及`chan` 46 | 47 | > 本质上,我们可以理解函数的传递都是值传递,只不过引用类型传递的是一个指向底层数据的指针,所以我们在操作的时候,可以修改共享的底层数据的值,进而影响到所有引用到这个共享底层数据的变量。 48 | 49 | ### 结构体类型 50 | 51 | 结构类型是用来描述一组值的,比如一个人有身高、体重、名字和年龄等,本质上是一种聚合型的数据类型。 52 | 53 | ```go 54 | type Person struct { 55 | age int 56 | name string 57 | } 58 | 59 | ``` 60 | 61 | 函数传参是值传递,所以对于结构体来说也不例外,结构体传递的是其本身以及里面的值的拷贝。 62 | 63 | -------------------------------------------------------------------------------- /go/function.md: -------------------------------------------------------------------------------- 1 | ## golang 函数 2 | 3 | ### 1. 函数的声明 4 | 5 | ```go 6 | func functionName(param type) returntype { 7 | 8 | } 9 | ``` 10 | 11 | 函数的声明使用`func` 关键字,后面跟着函数名。函数名后 跟着输入的参数,最后面的返回值。参数列表可以返回值不是必须的 12 | 13 | ```go 14 | func Sum(a int,b int) int{ 15 | return a + b 16 | } 17 | ``` 18 | 19 | 如果函数的参数是相同的类型,可以合并 20 | 21 | ```go 22 | func Sum(a,b int) int { 23 | return a+b 24 | } 25 | ``` 26 | 27 | ### 2. 多值返回 28 | 29 | golang 支持多值返回。我们常见的是返回一个错误 来判断里面的结果 30 | 31 | ```go 32 | func Sum(a int) (int,err) { 33 | return a,err 34 | } 35 | ``` 36 | 37 | ### 3. 命名返回 38 | 39 | 从函数中可以返回一个命名值。一旦命名了返回值,可以认为这些值在函数第一行就被声明为变量了。 40 | 41 | ```go 42 | func Sum(a,b int) (c int) { 43 | c = a+b 44 | } 45 | ``` 46 | 47 | 默认返回c 也不用return。 c默认就已经声明成变量了。 不需要使用`c:=` 来进行赋值了 48 | 49 | ### 4. 不定参数 50 | 51 | ```go 52 | func Sum(args ...int) (result int){ 53 | for _,v := args { 54 | result = result+v 55 | } 56 | } 57 | Sum(1,3,2,3) 58 | ``` 59 | 60 | -------------------------------------------------------------------------------- /go/gin.md: -------------------------------------------------------------------------------- 1 | Gin框架中间件实现 2 | 3 | ```go 4 | package main 5 | 6 | import "fmt" 7 | 8 | type HandlerFun func(c *Context) 9 | type Context struct { 10 | Handler []HandlerFun 11 | index int8 12 | } 13 | 14 | func (ctx *Context) Next() { 15 | ctx.index++ 16 | for ctx.index < int8(len(ctx.Handler)) { 17 | ctx.Handler[ctx.index](ctx) 18 | ctx.index++ 19 | } 20 | } 21 | func (ctx *Context) AddHandler(handlers ...HandlerFun) { 22 | ctx.Handler = append(ctx.Handler, handlers...) 23 | } 24 | func NewContext() *Context { 25 | return &Context{ 26 | Handler: make([]HandlerFun, 0), 27 | index: -1, 28 | } 29 | } 30 | 31 | func main() { 32 | ctx := NewContext() 33 | ctx.AddHandler(func(c *Context) { 34 | fmt.Println("1 begin") 35 | c.Next() 36 | fmt.Println("1 end") 37 | 38 | }, func(c *Context) { 39 | fmt.Println("2 begin") 40 | c.Next() 41 | fmt.Println("2 end") 42 | 43 | }, func(c *Context) { 44 | fmt.Println("3 begin") 45 | c.Next() 46 | fmt.Println("3 end") 47 | }) 48 | ctx.Next() 49 | } 50 | 51 | ``` 52 | -------------------------------------------------------------------------------- /go/go_noCloser.md: -------------------------------------------------------------------------------- 1 | 在http handler之前需要对body进行处理就带来了麻烦 2 | 由于 Request.Body 为公共变量,我们在对原有的buffer读取完成后,只要手动创建一个新的buffer然后以同样接口形式替换掉原有的Request.Body即可。 3 | 4 | 5 | ```go 6 | var bodyBytes []byte // 我们需要的body内容 7 | 8 | // 从原有Request.Body读取 9 | bodyBytes, err := ioutil.ReadAll(c.Request.Body) 10 | if err != nil { 11 | return 0, nil, fmt.Errorf("Invalid request body") 12 | } 13 | 14 | // 新建缓冲区并替换原有Request.body 15 | c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes)) 16 | 17 | // 当前函数可以使用body内容 18 | _ := bodyBytes 19 | ``` 20 | -------------------------------------------------------------------------------- /go/go_throw.md: -------------------------------------------------------------------------------- 1 | 在go语言中,有一些错误panic 我们可以通过`recover`来恢复,但是有一些语言底层抛的,致命错误,我们无法捕获 2 | 3 | ## throw 4 | throw 是最常见的错误。比如map并发读写不安全,就会出现致命错误 5 | 6 | ```go 7 | func test() { 8 | m := map[string]int{} 9 | 10 | go func() { 11 | for { 12 | m["a"] =1 13 | } 14 | }() 15 | 16 | go func() { 17 | for { 18 | _ = m["a"] 19 | } 20 | }() 21 | 22 | select{} 23 | } 24 | ``` 25 | 26 | ### 死锁 27 | 28 | ```go 29 | func f() { 30 | select{} 31 | 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /go/golang byte和rune.md: -------------------------------------------------------------------------------- 1 | ## golang rune 和int 之间的区别 2 | 3 | > rune is an alias for int32 and is equivalent to int32 in all ways. It is // used, by convention, to distinguish character values from integer values. 4 | 5 | 6 | 7 | 官方的解释,就是rune 在大部分情况都等于`int32` 8 | 9 | golang中string底层是通过byte数组实现的。 10 | 11 | ```go 12 | package main 13 | 14 | import "fmt" 15 | 16 | func main() { 17 | 18 | var str = "hello 你好" 19 | fmt.Println("len(str):", len(str)) //12 20 | fmt.Println(len([]rune(str))) //8 21 | 22 | } 23 | 24 | ``` 25 | 26 | 27 | 28 | - byte 等同于int8,常用来处理ascii字符 29 | - rune 等同于int32,常用来处理unicode或utf-8字符 30 | 31 | 1字节=8位(1 byte = 8bit【位】) 32 | 在英文字符中一个字符占一个字节。 33 | 字符0 在ascii编码中就是0011 0000 34 | 换成十进制就是48 35 | 36 | 都是标识原始字符数据。 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /go/gopath.md: -------------------------------------------------------------------------------- 1 | # gopath基础概念 2 | 3 | ## GOROOT 4 | 5 | `GOROOT` 就是golang的安装目录。 6 | 7 | ## GOBIN 8 | 9 | go install编译存放路径。**不允许**设置多个路径。可以为空。为空时则遵循“约定优于配置”原则,可执行文件放在各自**GOPATH目录的bin**文件夹中(前提是:package main的main函数文件不能直接放到GOPATH的src下面。 10 | 11 | ## GOPATH 12 | 13 | go命令依赖的一个重要环境变量:`$GOPATH `其实可以把这个目录理解为工作目录 14 | 15 | 具体用途:go命令常常需要用到的,如go run,go install, go get等。允许设置多个路径,和各个系统环境多路径设置一样,windows用“;”,linux(mac)用“:”分隔。 16 | 17 | ``` 18 | goWorkSpace // (goWorkSpace为GOPATH目录) 19 | -- bin // golang编译可执行文件存放路径,可自动生成。 20 | -- pkg // golang编译的.a中间文件存放路径,可自动生成。 21 | -- src // 源码路径。按照golang默认约定,go run,go install等命令的当前工作路径(即在此路径下执行上述命令)。 22 | ``` 23 | 24 | ### Go目录结构 25 | 26 | ``` 27 | project1 // (project1添加到GOPATH目录了) 28 | -- bin 29 | -- pkg 30 | -- src 31 | -- models // package 32 | -- controllers // package 33 | -- main.go // package main[注意,本文所有main.go均指包main的入口函数main所在文件] 34 | project2 // (project2添加到GOPATH目录了) 35 | -- bin 36 | -- pkg 37 | -- src 38 | -- models // package 39 | -- controllers // package 40 | -- main.go // package main 41 | ``` 42 | 43 | ### go get [main.go所在路径] 44 | 45 | 参数 [main.go所在路径]:可选。相对GOPATH/src路径。 缺省是.(src自己)。可指定src下面的子文件夹路径。  go get会做2件事: 46 | 47 | 1. 从远程下载需要用到的包。 48 | 2. 2.执行go install。 49 | 50 | 51 | 52 | ### go install [main.go所在路径] 53 | 54 | 参数 [main.go所在路径]:可选。 相对**GOPATH/src**路径。缺省是.(即当前所在目录或工作目录)。可指定src下面的子文件夹。 55 | `go install`编译生成名称为[`main.go`父文件夹名]的可执行文件,放到GOBIN路径下。当GOBIN为空时,默认约定是:生成的可执行文件放到`GOPATH/bin`文件夹中。产生的中间文件(.a)放在project/pkg中(没有变化时,不重新生成.a)。 56 | -------------------------------------------------------------------------------- /go/json.md: -------------------------------------------------------------------------------- 1 | ## json 序列化 2 | 3 | ### 1. omitempty 4 | 5 | 当值为空的时候,序列化会忽略掉该字段 6 | ```go 7 | type Demo struct { 8 | Ids *[]int `json:"ids,omitempty"` 9 | } 10 | 11 | func main() { 12 | var arr []int 13 | d := &Demo{ 14 | Ids: &arr, 15 | } 16 | b, _ := json.Marshal(d) 17 | fmt.Println(string(b)) // {"ids":null} 18 | 19 | d2 := &Demo{Ids: nil} 20 | b,_ := json.Marshal(d2) 21 | fmt.Println(string(b)) // {} 22 | } 23 | 24 | ```` 25 | -------------------------------------------------------------------------------- /go/map&array&struct.md: -------------------------------------------------------------------------------- 1 | ## array、map、struct 2 | 3 | 数组、字典map、结构体是golang常见的数据类型。有时候我们写PHP的可能会分不清,但是有必要说明下区别/ 4 | 5 | ### 1. 数组 6 | 7 | 数组就是用下标为**数字**来标识的值的位置,在地址空间上,数组中的每个元素都是连续的 8 | 9 | ```go 10 | arr1 := [3]int8{0, 1, 2} 11 | for i := 0; i < 3; i++ { 12 | fmt.Println(&arr1[i]) 13 | } 14 | ``` 15 | 16 | ### 2. 字典 17 | 18 | 字典就是哈希表, k=>v的结构。,只是值可以是字符或者其他类型。字典的key必须是同一个类型。不能像php一样,包含多个类型。 19 | 20 | ```go 21 | map1 := make(map[string]string) 22 | map1["a"] ="aaaa" 23 | map1["b"] = "bbb" 24 | map2 := map[string]string{"a": "a1", "b": "b1"} 25 | ``` 26 | 27 | ### 3. 结构体 28 | 29 | 结构体就是和C语言结构体一样,是定义多个多个复合类型的集合。比如里面既可以又整型,也可以有字符等。 30 | 31 | ```go 32 | type Person struct{ 33 | age int 34 | name string 35 | } 36 | 37 | ``` 38 | 39 | 40 | 41 | ### 总结 42 | 43 | map和array则是定义一组数据,他们的数据类型是相同的。而结构体定义的类型则是不相同的。 44 | 45 | 比如我们要定义一个学生的姓名的列表。这个时候,我们可以使用map或是array。因为学生的姓名基本上类型一致 都是string。但是如果我们需要定义一个学生的属性信息,一个学生有年龄,姓名,班级。这个时候,我们就需要使用结构体了。 46 | -------------------------------------------------------------------------------- /go/new & make.md: -------------------------------------------------------------------------------- 1 | ## new & make 2 | 3 | new 和make 都是内置函数,用来分配内存变量 4 | 5 | ### 变量的声明 6 | 7 | ```go 8 | var i int 9 | var s string 10 | ``` 11 | 12 | 变量的声明我们可以通过`var`关键字,然后就可以在程序中使用。当我们不指定变量的默认值时,这些变量的默认值是他们的零值,比如`int`类型的零值是0,`string`类型的零值是`""`,引用类型的零值是`nil`。 13 | 14 | 对于引用类型需要赋值的时候,就需要用到new和make。 15 | 16 | ### new 17 | 18 | new 返回是是类型的指针。指向分配类型的地址。 19 | 20 | ``` 21 | var i = new(int) 22 | 23 | *i = 10; 24 | ``` 25 | 26 | ### make 27 | 28 | `make`也是用于内存分配的,但是和`new`不同,它只用于**`chan`、`map`以及切片**的内存创建,而且它**返回的类型就是这三个类型本身**,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了 29 | 30 | ``` 31 | var m = make(maps[string]string) 32 | ``` 33 | 34 | 35 | 36 | ### 参考资料 37 | 38 | - [https://www.flysnow.org/2017/10/23/go-new-vs-make.html](https://www.flysnow.org/2017/10/23/go-new-vs-make.html) 39 | 40 | -------------------------------------------------------------------------------- /go/package.md: -------------------------------------------------------------------------------- 1 | ## package 2 | 3 | - 每个go源码文件必须拥有一个package声明,表示golang代码所在的package 4 | - 要生成golang执行程序,必须有一个名为**main**的package。在这个package里面必须有一个**main**的函数 **main包+main函数** 5 | - 同一个路径下只能存在一个package。一个package可以拆解成多个源文件 6 | 7 | ### 工程目录结构 8 | 9 | ``` 10 | study 11 | |---src 12 | |--a 13 | |--add.go 14 | |--sum.go 15 | ``` 16 | 17 | add.go 18 | 19 | ```go 20 | package a 21 | 22 | type A struct{ 23 | 24 | } 25 | function Add() { 26 | 27 | } 28 | ``` 29 | 30 | ### import 的用法 31 | 32 | import 调用原理 33 | 34 | ![img](https://images2015.cnblogs.com/blog/526315/201601/526315-20160125172231942-864886599.png) 35 | 36 | - import 包名 37 | 38 | ```go 39 | package main 40 | import "a" 41 | import ( 42 | "a" 43 | ) 44 | ``` 45 | 46 | 47 | 48 | - 点(.)操作 49 | 50 | 点操作,意思是导入包之后,调用该包的时候,可以省略包名 51 | 52 | ```go 53 | package main 54 | import . "fmt" 55 | 56 | func main() { 57 | Println("hello world") 58 | } 59 | ``` 60 | 61 | - 别名操作 62 | 63 | 别名操作的含义是:将导入的包命名为另一个容易记忆的别名 64 | 65 | ```go 66 | import p "fmt" 67 | 68 | func main() { 69 | p.Println("hello") 70 | } 71 | ``` 72 | 73 | - 下划线操作。 74 | 75 | 线(`_`)操作的含义是:导入该包,但不导入整个包,而是执行该包中的init函数,因此无法通过包名来调用包中的其他函数。使用下划线(_)操作往往是为了注册包里的引擎,让外部可以方便地使用 就是类型与构造 76 | 77 | ```go 78 | package a 79 | 80 | func init() { 81 | fmt.Println("init") 82 | } 83 | //main 84 | package main 85 | import _ "a" 86 | func main () { 87 | 88 | } 89 | ``` 90 | 91 | 92 | -------------------------------------------------------------------------------- /go/time.md: -------------------------------------------------------------------------------- 1 | 2 | ## **Go时间戳和日期字符串的相互转换** 3 | 4 | 获取时间戳用 `time.Now().Unix()`,格式化时间用 `t.Format`,解析时间用`time.Parse`。 5 | 6 | 格式化时间格式 `2006-01-02 15:04:05` 记忆方法 1月2号3点4分5秒6年 7 | 8 | ```go 9 | import ( 10 | "fmt" 11 | "time" 12 | ) 13 | func main() { 14 | //获取当前时间戳 15 | fmt.Println(time.Now().Unix()) 16 | timeTpl := "2006-01-02 15:04:05" 17 | fmt.Println(time.Now.Unix().Format(timeTpl)) 18 | t := "2001-01-02 13:09:21" 19 | time.Parse(timeTpl,t) 20 | } 21 | ``` 22 | 23 | - 时间戳转时间 24 | 25 | ```go 26 | timestamp := 1564483130 27 | time.Unix(int64(timestamp),1).Format("2006-01-02 15:04:05") 28 | ``` 29 | 30 | - 时间转时间戳 31 | 32 | ```go 33 | t := "2018-01-02 01:02:03" 34 | T,_ := t.Parse("2006-01-02 15:04:05",t) 35 | T.Unix() 36 | ``` 37 | 38 | 39 | 40 | **格式化时间字符串** 41 | 42 | - 月份 1,01,Jan,January 43 | 44 | - 日  2,02,_2 45 | 46 | - 时  3,03,15,PM,pm,AM,am 47 | 48 | - 分  4,04 49 | 50 | - 秒  5,05 51 | 52 | - 年  06,2006 53 | 54 | - 周几 Mon,Monday 55 | 56 | - 时区时差表示 -07,-0700,Z0700,Z07:00,-07:00,MST 57 | 58 | - 时区字母缩写 MST 59 | -------------------------------------------------------------------------------- /go/unsafe.md: -------------------------------------------------------------------------------- 1 | 利用golang unsafe读取私有变量 2 | unsafe.Pointer是一种特殊意义的指针,它可以包含任意类型的地址 3 | 4 | ```go 5 | //a.go 6 | type bodyJson struct { 7 | v interface{} 8 | } 9 | 10 | func Body(a interface{}) *bodyJson{ 11 | 12 | return &bodyJson{v:a} 13 | } 14 | 15 | //b.go 16 | 17 | type Temp struct { 18 | v interface{} 19 | } 20 | 21 | s := a.Body(1212) 22 | t := (*Temp)(unsafe.Pointer(&s)) 23 | 24 | fmt.Println(t.v) 25 | 26 | 27 | ``` 28 | -------------------------------------------------------------------------------- /go/交叉编译.md: -------------------------------------------------------------------------------- 1 | Golang 支持交叉编译,在一个平台上生成另一个平台的可执行程序,最近使用了一下,非常好用,这里备忘一下。 2 | 3 | Mac 下编译 Linux 和 Windows 64位可执行程序 4 | ``` 5 | CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go 6 | CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go 7 | ``` 8 | 9 | Linux 下编译 Mac 和 Windows 64位可执行程序 10 | ``` 11 | CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go 12 | CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go 13 | ``` 14 | 15 | Windows 下编译 Mac 和 Linux 64位可执行程序 16 | ``` 17 | SET CGO_ENABLED=0 18 | SET GOOS=darwin 19 | SET GOARCH=amd64 20 | go build main.go 21 | 22 | SET CGO_ENABLED=0 23 | SET GOOS=linux 24 | SET GOARCH=amd64 25 | go build main.go 26 | ``` 27 | - GOOS:目标平台的操作系统(darwin、freebsd、linux、windows) 28 | - GOARCH:目标平台的体系架构(386、amd64、arm) 29 | 交叉编译不支持 CGO 所以要禁用它 30 | -------------------------------------------------------------------------------- /redis/Redis-Bitmap操作.md: -------------------------------------------------------------------------------- 1 | ## Redis Bitmap 2 | 3 | BitMap是什么 4 | bitmap就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身。我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省储存空间. 5 | 6 | ![](https://imgsa.baidu.com/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=8172ae52d31373f0e13267cdc566209e/d52a2834349b033b0b84caf317ce36d3d539bd8e.jpg) 7 | 8 | - SETBIT 9 | 10 | 设置或者清空key的value(字符串)在offset处的bit值(只能只0或者1)。 11 | 大概的空间占用计算公式是: ($offset/8/1024/1024)MB 12 | 13 | SETBIT key offset value 14 | 15 | - GETBIT 16 | 17 | 返回key对应的string在offset处的bit值 18 | 19 | GETBIT key offset 20 | 21 | - BITCOUNT 22 | 23 | 统计字符串被设置为1的bit数 24 | 25 | BITCOUNT key [start end] 26 | 27 | - BITPOS key bit [start] [end] 28 | 29 | 返回字符串里面第一个被设置为1或者0的bit位。 30 | 31 | BITPOS key bit [start] [end] 32 | 33 | - BITOP 34 | 35 | > 对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。 36 | BITOP 命令支持 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种参数: 37 | BITOP AND destkey srckey1 srckey2 srckey3 ... srckeyN ,对一个或多个 key 求逻辑并,并将结果保存到 destkey 。 38 | BITOP OR destkey srckey1 srckey2 srckey3 ... srckeyN,对一个或多个 key 求逻辑或,并将结果保存到 destkey 。 39 | BITOP XOR destkey srckey1 srckey2 srckey3 ... srckeyN,对一个或多个 key 求逻辑异或,并将结果保存到 destkey 。 40 | BITOP NOT destkey srckey,对给定 key 求逻辑非,并将结果保存到 destkey 。 41 | 除了 NOT 操作之外,其他操作都可以接受一个或多个 key 作为输入。 42 | 执行结果将始终保持到destkey里面。 43 | 44 | BITOP operation destkey key 45 | 46 | ## 使用场景 47 | 48 | 1. 使用 bitmap 实现用户上线次数统计 49 | 50 | 假设现在我们希望记录自己网站上的用户的上线频率,比如说,计算用户 A 上线了多少天,用户 B 上线了多少天,用户今天登陆了网站就在用户的key中加1. 51 | 52 | setbit user1 10 1 53 | setbit user1 11 1 54 | bitget user1;//11 55 | 56 | 2. 统计活跃用户 57 | 58 | 使用时间作为cacheKey,然后用户ID为offset,如果当日活跃过就设置为1 59 | 60 | setbit 2017-05-21 11 1 61 | setbit 2017-05-21 12 1 62 | bitcount 2017-05-21 //2 -------------------------------------------------------------------------------- /redis/Redis发布订阅.md: -------------------------------------------------------------------------------- 1 | ## Redis 发布/订阅 2 | 3 | > Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息 4 | 5 | ![](http://www.runoob.com/wp-content/uploads/2014/11/pubsub2.png) 6 | 7 | 可以作为消息队列 8 | 9 | 10 | - PUBLISH 11 | 12 | Publish 命令用于将信息发送到指定的频道 13 | 14 | PUBLISH channel message 15 | 16 | - SUBSCRIBE 17 | 18 | Subscribe 命令用于订阅给定的一个或多个频道的信息。 19 | 20 | SUBSCRIBE channel [channel ...] 21 | 22 | 23 | - UNSUBSCRIBE 24 | 25 | Unsubscribe 命令用于退订给定的一个或多个频道的信息 26 | 27 | UNSUBSCRIBE channel -------------------------------------------------------------------------------- /redis/Redis有序集合.md: -------------------------------------------------------------------------------- 1 | ## Redis Zset 有序集合 2 | 3 | > Zset就是有序集合,除了集合的特性外还对每一个集合元素添加了一个顺序的属性. 4 | 例如 myzset = {1=>c,3=>d,2=>e} 5 | 6 | | row(索引)| value(值)| score(序号) | 7 | | ------------- |:-------------:| -----:| 8 | | 1 | c | 1 | 9 | | 2 | d | 3 | 10 | | 3 | e | 2 | 11 | 12 | - ZADD 13 | 14 | 添加一个有序集合 15 | 16 | 语法:ZADD 集合名 序号 集合元素 17 | 18 | zadd myzset 1 "one" 19 | 20 | - ZRAGE 21 | 22 | 返回对应区间的有序集合 23 | 24 | 语法:ZRANGE 集合名 开始位置 结束位置 25 | 26 | ZRANGE myset 1 2 27 | 28 | - ZCARD 29 | 30 | 返回有序集合中的数量 31 | 32 | ZCARD myset 33 | 34 | - ZCOUNT 35 | 36 | 返回有序集合制定序列之间的元素个数 37 | 38 | ZRANGE myzset 0 1 39 | 40 | - ZINCRBY 41 | 42 | 为元素的序号进行自增 43 | 44 | ZINCRBY myzset 2 'one' 45 | 46 | - ZREVRANGE 47 | 48 | 倒序显示有序集合 49 | 50 | 51 | - zrank 52 | 53 | 显示某个元素在有序集合中的序号 54 | 55 | myzset = {c,d,e,w,a,p,m} 56 | zrank myzset a //4 57 | 58 | - ZREM 59 | 60 | 删除元素 61 | 62 | zrem myzset a 63 | 64 | - ZREMRANGEBYRANK 65 | 66 | 删除指定范围内的元素 通过索引 67 | 68 | ZREMRANGEBYRANK myzset 0 2 69 | 70 | - ZREMRANGEBYSCORE 71 | 72 | 删除指定序号内的元素 通过序号 73 | 74 | ZREMRANGEBYSCORE myzset 0 2 75 | 76 | - ZSCORE 77 | 78 | 显示元素的序号 79 | 80 | ZSCORE myzset a 81 | -------------------------------------------------------------------------------- /redis/Redis键值命令.md: -------------------------------------------------------------------------------- 1 | ## Redis keys 相关的命令 2 | 3 | - del 4 | 5 | 删除一个key 6 | 7 | del key1 8 | 9 | - EXISTS 10 | 11 | 查看一个键是否存在 12 | 13 | EXISTS key1 14 | 15 | - EXPIRE 16 | 17 | 设置key的过期时间 18 | 19 | EXPIRE key1 20 | 21 | - EXPIREAT 22 | 23 | 设置key的过期时间,有效数值是是一个 unix时间戳 24 | 25 | EXPIREAT 1495358097 26 | 27 | - KEYS 28 | 29 | 查找所有符合给定模式pattern(正则表达式)的 key 30 | 31 | KEYS * 查看所有的key 32 | 33 | - TYPE 34 | 35 | 查看key的类型 36 | 37 | TYPE key1 // hash|list|string 38 | 39 | - TTL 40 | 41 | 查看key的剩余过期时间 42 | 43 | TTL KEY // -1yon 44 | 45 | 如果key不存在或者已过期,返回 -2 46 | 如果key没有设置过期时间(永久有效),返回 -1 。 47 | 48 | - RANDOMKEY 49 | 50 | 随机返回一个key 51 | 52 | RANDOMKEY 53 | 54 | - RENAME 55 | 56 | 给一个key重新命名 57 | 58 | RENAME key newkey 59 | 60 | - PERSIST 61 | 62 | 移除给定key的生存时间,将这个 key 从『易失的』(带生存时间 key )转换成『持久的』(一个不带生存时间、永不过期的 key )。 -------------------------------------------------------------------------------- /redis/SDS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/redis/SDS.png -------------------------------------------------------------------------------- /redis/dict.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/redis/dict.png -------------------------------------------------------------------------------- /redis/intset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/redis/intset.png -------------------------------------------------------------------------------- /redis/redis开发规则.md: -------------------------------------------------------------------------------- 1 | ## Redis 开发规范 2 | 3 | ### 1. 键名建议 4 | 5 | - 可读性和可管理性 6 | 7 | 以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔,比如业务名:表名:id。 8 | 9 | - 简洁性 10 | 11 | 保证语义的前提下,控制key的长度,当key较多时,内存占用也不容忽视 12 | 13 | - 不允许包括特殊字符 14 | 15 | 不能包含空格、换行、单双引号以及其他转义字符 16 | 17 | 18 | 19 | ### 2. Value 建议 20 | 21 | - 拒绝大key 22 | 23 | string类型控制在10KB以内,hash、list、set、zset元素个数不要超过5000。 24 | 25 | - 选择合适的数据类型 26 | 27 | - 控制key的生命周期,redis不是垃圾桶。 28 | 29 | 建议使用expire设置过期时间(条件允许可以打散过期时间,防止集中过期),不过期的数据重点关注idletime。 30 | 31 | 项目里一般强制要求所有都设置过期时间,避免由于redis问题导致服务不可用 32 | 33 | ### 3. 命令使用 34 | 35 | - O(N)命令 关注N的数量 36 | 37 | - 禁用命令 38 | 39 | 禁止线上使用keys、flushall、flushdb等,通过redis的rename机制禁掉命令,或者使用scan的方式渐进式处理。 40 | 41 | - 推荐使用批量操作,提高效率 42 | 43 | 原生命令:例如mget、mset。 非原生命令:可以使用pipeline提高效率。 44 | 45 | - redis 事务性能弱,不建议使用 46 | 47 | 48 | 49 | ## 参考资料 50 | 51 | - [https://yq.aliyun.com/articles/557508](https://yq.aliyun.com/articles/557508) 52 | -------------------------------------------------------------------------------- /redis/ziplist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/redis/ziplist.png -------------------------------------------------------------------------------- /其他/2018-09-12.md: -------------------------------------------------------------------------------- 1 | - [x] mysql 查找重复数据 2 | 3 | ```sql 4 | SELECT name, COUNT(*) c FROM table GROUP BY name HAVING c > 1; 5 | 6 | ``` 7 | 8 | - [x] clickhouse 聚合函数 [https://note.abeffect.com/note/articles/2018/01/24/1516782829665.html](https://note.abeffect.com/note/articles/2018/01/24/1516782829665.html) 9 | 10 | - [x] Nginx realpath 11 | 12 | ``` 13 | http { 14 | disable_symlinks off; 15 | } 16 | fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; 17 | fastcgi_param DOCUMENT_ROOT $realpath_root; 18 | ``` -------------------------------------------------------------------------------- /其他/aes.md: -------------------------------------------------------------------------------- 1 | ## **AES**,高级加密标准 2 | (英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。 3 | 4 | 1. AES的区块长度固定为128 比特,密钥长度则可以是128,192或256比特;而Rijndael使用的密钥和区块长度可以是32位的整数倍,以128位为下限,256比特为上限。 5 | 6 | 三种填充模式 7 | 8 | - ZeroPadding,数据长度不对齐时使用0填充,否则不填充。 9 | - PKCS7Padding,假设数据长度需要填充n(n>0)个字节才对齐,那么填充n个字节,每个字节都是n;如果数据本身就已经对齐了,则填充一块长度为块大小的数据,每个字节都是块大小。 10 | - PKCS5Padding,PKCS7Padding的子集,块大小固定为8字节。针对des 11 | 12 | AES的参数 13 | 14 | 1. key length(密钥位数,密码长度) 15 | AES128,AES192,AES256(128 位、192 位或 256 位) 16 | 2. key (密钥,密码) 17 | 18 | key指的就是密码了,AES128就是128位的,如果位数不够,某些库可能会自动填充到128。 19 | 20 | 3. IV (向量) 21 | 22 | IV称为初始向量,不同的IV加密后的字符串是不同的,加密和解密需要相同的IV 23 | 24 | 4. mode (加密模式) 25 | 26 | AES分为几种模式,比如ECB,CBC,CFB等等,这些模式除了ECB由于没有使用IV而不太安全,其他模式差别并没有太明显 27 | 28 | 5. padding (填充方式) 29 | 30 | 对于加密解密两端需要使用同一的PADDING模式,大部分PADDING模式为PKCS5, PKCS7, ZEROPADDING。 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /其他/images/1536130176419.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536130176419.png -------------------------------------------------------------------------------- /其他/images/1536130356026.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536130356026.png -------------------------------------------------------------------------------- /其他/images/1536130606998.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536130606998.png -------------------------------------------------------------------------------- /其他/images/1536130879493.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536130879493.png -------------------------------------------------------------------------------- /其他/images/1536131596474.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536131596474.png -------------------------------------------------------------------------------- /其他/images/1536131722713.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536131722713.png -------------------------------------------------------------------------------- /其他/images/1536131772127.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536131772127.png -------------------------------------------------------------------------------- /其他/images/1536131936983.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536131936983.png -------------------------------------------------------------------------------- /其他/images/1536132188638.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536132188638.png -------------------------------------------------------------------------------- /其他/images/1536132302256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536132302256.png -------------------------------------------------------------------------------- /其他/images/1536132609448.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536132609448.png -------------------------------------------------------------------------------- /其他/images/1536132748160.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536132748160.png -------------------------------------------------------------------------------- /其他/images/1536133092580.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536133092580.png -------------------------------------------------------------------------------- /其他/images/1536133387168.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536133387168.png -------------------------------------------------------------------------------- /其他/images/1536133451273.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536133451273.png -------------------------------------------------------------------------------- /其他/images/1536133508626.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536133508626.png -------------------------------------------------------------------------------- /其他/images/1536133605461.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536133605461.png -------------------------------------------------------------------------------- /其他/images/1536133804975.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536133804975.png -------------------------------------------------------------------------------- /其他/images/1536133876981.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536133876981.png -------------------------------------------------------------------------------- /其他/images/1536133911407.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536133911407.png -------------------------------------------------------------------------------- /其他/images/1536134070135.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536134070135.png -------------------------------------------------------------------------------- /其他/images/1536134215544.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536134215544.png -------------------------------------------------------------------------------- /其他/images/1536134393112.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536134393112.png -------------------------------------------------------------------------------- /其他/images/1536135094157.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xianyunyh/studynotes/264a7409cc36c1757bbb7a779a8f509edbbc5006/其他/images/1536135094157.png -------------------------------------------------------------------------------- /其他/make-nginx-follow-symlinks.md: -------------------------------------------------------------------------------- 1 | ## Nginx 支持LInux 的链接目录 2 | 3 | 今天在给网站nginx 增加一个vhost的时候,将`root` 指向了一个 目录的软链接。结果发现nginx 不支持。查阅文档,发现可以通过通配置打开. 4 | 5 | ```ini 6 | http { 7 | disable_symlinks off; 8 | } 9 | ``` 10 | 11 | 12 | 13 | 如果配置了php的话。需要在fastcig_params把`document_root` 改成` realpath_root` 14 | 15 | ```ini 16 | fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; 17 | fastcgi_param DOCUMENT_ROOT $realpath_root; 18 | ``` 19 | 20 | 更改完,然后重启nginx 就ok 了, -------------------------------------------------------------------------------- /其他/maven.md: -------------------------------------------------------------------------------- 1 | maven镜像更改 2 | 配置文件在 maven安装目录 在conf下 **setting.xml** 3 | 4 | 5 | ```xml 6 | 7 | 8 | alimaven 9 | aliyun maven 10 | http://maven.aliyun.com/nexus/content/groups/public/ 11 | central 12 | 13 | 14 | ``` 15 | -------------------------------------------------------------------------------- /其他/polipo shadowsocks to http.md: -------------------------------------------------------------------------------- 1 | ## 用polipo将shadowsocks转换为http代理 2 | 3 | 最近一直使用python爬取数据,但是有时总是被封ip,就想到了用代理ip的方法。但是网上的代理,都不怎么好用,经常失效,于是 就想自己搭建一个,在搜索的过程中,了解到了pilipo可以将socket转成http代理。之前自己搭建过一个sockets5作为fq用,于是就用到了这个polipo将请求转化即可。 4 | 5 | - shadowsockets 大家都知道。假设本地客户端默认是1080端口 6 | 7 | ### 安装polipo 8 | 9 | windows下面下载地址:[https://www.irif.fr/~jch/software/files/polipo/polipo-1.0.4-win32.zip](https://www.irif.fr/~jch/software/files/polipo/polipo-1.0.4-win32.zip) 10 | 11 | 下载完,解压即可。需要修改几个参数 12 | 13 | 默认配置文件`config.sample` 加入或修改以下配置 14 | 15 | ```ini 16 | socksParentProxy = "127.0.0.1:1080" 17 | 18 | socksProxyType = socks5 19 | ``` 20 | 21 | ### 运行 22 | 23 | ``` 24 | polipo.exe -c config.sample 25 | ``` 26 | 27 | 28 | 29 | 然后配置自己的系统代理,就可以使用HTTP代理了 -------------------------------------------------------------------------------- /其他/shadowsocket限速.md: -------------------------------------------------------------------------------- 1 | ## shadowsocket 限速 2 | 3 | 由于自己的服务器开的ss账户越来越多了,导致自己使用也不方便,于是就想能不能限速下,保证自己正常使用的情况,想了下,流量是通过端口进来的,通过iptables应该可以控制,搜索了一下,找到方案 4 | 5 | ### 限制端口连接数量 6 | 7 | - 首先输入命令service iptables stop关闭iptables 8 | - 限制端口并发数很简单,IPTABLES就能搞定了,假设你要限制端口`8388`的IP最大连接数为5,两句话命令: 9 | 10 | ```bash 11 | iptables -I INPUT -p tcp --dport 8388 -m connlimit --connlimit-above 5 -j DROP 12 | iptables -I OUTPUT -p tcp --dport 8388 -m connlimit --connlimit-above 5 -j DROP 13 | ``` 14 | 15 | ### 限制端口速度 16 | 17 | ```bash 18 | iptables -A INPUT -p tcp --sport 5037 -m limit --limit 60/s -j ACCEPT 19 | iptables -A INPUT -p tcp --sport 5037 -j DROP 20 | ``` 21 | 22 | 也就是限制每秒接受60个包,一般来说每个包大小为`64—1518`字节(Byte)。 23 | 24 | ### 限制指定ip的访问速度 25 | 26 | 原理:每秒对特定端口进行速度控制,比如每秒超过10个的数据包直接DROP,从而限制特定端口的速度 27 | 28 | ```bash 29 | iptables -A FORWARD -m limit -d 208.8.14.53 --limit 700/s --limit-burst 100 -j ACCEPT 30 | iptables -A FORWARD -d 208.8.14.53 -j DROP 31 | ``` 32 | 33 | **最后不要忘记重启防火墙 ** 34 | 35 | ```bash 36 | service iptables restart 37 | ``` 38 | 39 | 如果启动失败可以尝试以下解决方法 40 | 41 | ```bash 42 | iptables-save >/etc/sysconfig/iptables 43 | echo 'iptables-restore /etc/sysconfig/iptables' >> /etc/rc.local 44 | chmod +x /etc/rc.d/rc.local 45 | ``` 46 | 47 | -------------------------------------------------------------------------------- /操作系统/2.操作启动.md: -------------------------------------------------------------------------------- 1 | ## 操作启动 2 | 3 | 硬盘存放操作系统。BIOS基本IO处理系统。自检。 4 | 5 | bootloader 加载操作系统。放在硬盘的第一个主引导扇区(512字节)。 6 | 7 | BIOS 从特定的地址开始执行。从段寄存器、ip指定寄存器开始执行。 8 | 9 | 1. POST自检(加电自检)。寻找显卡和Bios 10 | 2. bootload 把操作系统的代码和数据加载到内存,跳转到操作系统的起始位置。 11 | 12 | 13 | 14 | ## 操作系统交互 15 | 16 | 系统调用:应用程序向操作系统发出服务请求。(来源应用程序) 17 | 18 | 异常:非法的指令,(来源不良的应用程序) 19 | 20 | 中断:(来源外设) 21 | 22 | 在操作系统中,内核被信任的第三方。只有内核执行第三方的指令。屏蔽底层的复杂性。 23 | 24 | 25 | 26 | 处理时间: 27 | 28 | - 中断:异步事件 29 | - 异常:同步 30 | - 系统调用:异步或同步 31 | 32 | 响应状态 33 | 34 | - 中断:持续 对用户应用程序是透明的 35 | - 异常:杀死异常的程序。重试 36 | - 系统调用:等待和持续(等待服务完成) 37 | 38 | 39 | 40 | 硬件 设置中断标记(),将内部、外部事件设置中断标记,记录中断id。 41 | 42 | 操作系统需要保存被打乱的状态保持。中断服务,清除中断标记。 43 | 44 | 中断 设置中断表。 45 | 46 | 设置中断标记 47 | 48 | 49 | 50 | 异常(比如 /0 操作) 51 | 52 | - 保存现场 53 | - 异常处理 杀死程序。或重新执行指令 54 | - 恢复现场 55 | 56 | 57 | 58 | 59 | 60 | 系统调用(系统系统调用接口) 61 | 62 | 比如应用程序调用printf。会触发系统调用write系统。访问对应的设备io。 63 | 64 | - win32 api 用于windows 65 | - POSIX API 66 | 67 | 通常情况下。与每个系统调用相关的序号。 68 | 69 | application->库->系统调用 70 | 71 | 系统调用和函数调用。 72 | 73 | 函数调用在一个栈的空间内完成了数据的返回。 74 | 75 | 系统调用:切换堆栈,内核态和用户态切换。系统开销大。 76 | 77 | 78 | 79 | 系统调用的开销 80 | 81 | 在执行时间上的开销超过程序调用。 82 | 83 | 建立中断、异常、系统调用号与对应服务 84 | 85 | 建立内核堆栈。不能为用户的堆栈混淆。 86 | 87 | 内核态映射到用户态的地址空间 88 | 89 | 内核态独立地址空间。 -------------------------------------------------------------------------------- /操作系统/3.操作系统内存管理.md: -------------------------------------------------------------------------------- 1 | ### 计算机体系结构和内存分层体系 2 | 3 | 4 | 5 | 计算机基本硬件结构:CPU(运算器、寄存器、缓存、控制器、存储管理单元(MMU))、内存、设备(IO) 6 | 7 | 内存的层次结构:(寄存器-》L1缓存-》L2缓存)=》主存(物理内存)=》磁盘(虚拟内存) 8 | 9 | **操作系统在内存管理的作用** 10 | 11 | - **抽象** 逻辑地址空间 12 | - **保护** 独立地址空间 13 | - **共享** 访问相同内存 14 | - **虚拟化** 更多的地址空间 15 | 16 | 17 | 18 | ### 地址空间和地址生成 19 | 20 | 物理地址空间。硬件支持的地址空间。如内存的大小、磁盘的大小。 21 | 22 | 逻辑地址空间。一个运行的程序所拥有的内存范文。一维数组。起始地址是0x0000 23 | 24 | MMU 逻辑地址到物理地址映射。 25 | 26 | ### 内存分配 27 | 28 | 内存碎片 29 | 30 | 空闲内存不能被利用 31 | 32 | 外部碎片、内部碎片(已经分配,未使用) 33 | 34 | 内分分配:首次适配、最优适配、最差适配 35 | 36 | 比如在内存中有三个空闲的内存块1k、2k、500B 37 | 38 | 我们申请400b。 首次适配则分配到第一个连续块1k。最优适配则申请到500b,最差适配则申请到2k 39 | 40 | 首次适配:为了分配N字节。分配一个可用块以致快的的大小比N大。 41 | 42 | 按地址的空闲块列表。重新分配需要检查。 43 | 44 | 优点:简单,易于产生更大空间。缺点:产生外部碎片。 45 | 46 | 最优适配:寻找内存中最适合的内存块。就是内存块最小的。避免大块进行拆分。 47 | 48 | 优点:对小内存块有效。缺点:产生碎片。 49 | 50 | 最差适配:找到一个空闲内存块,差距最大的块。 51 | 52 | 避免产生小碎片。重新分配慢,产生碎片。 53 | 54 | ### 碎片管理 55 | 56 | 压缩碎片管理 57 | 58 | 交换碎片管理。 59 | 60 | 将等待的程序中的内存数据放入硬盘。 61 | 62 | 运行程序需要更多的内存, 63 | 64 | 抢占等待的程序 & 回收他们的内存。 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /操作系统/临界区.md: -------------------------------------------------------------------------------- 1 | ## 临界区 2 | 3 | - **屏蔽硬件终端** 4 | 5 | 没有终端,没有上下文切换,因此没有并发。 6 | 7 | 进入临界区,禁止中断。 8 | 9 | 离开临界区,开启中断 10 | 11 | - **基于软件的抽象** 12 | 13 | ``` 14 | do { 15 | 进入 16 | 离开 17 | 提醒 18 | } 19 | ``` 20 | 21 | 使用两个共享数据项 22 | 23 | int turn 指示进入临界区 24 | 25 | bolean flag[] 指示进程是否准备好进入临界区 26 | 27 | 进入临界区操作 28 | 29 | flag[i] = true 30 | 31 | turn = j; 32 | 33 | while(flag[j] && turn == j) 34 | 35 | 退出临界区 36 | 37 | flag[i] = false; 38 | 39 | - **更高级的抽象** 原子操作指令 40 | 41 | 硬件提供了一些原语 42 | 43 | 1. 像中断禁用,原子操作指令 44 | 45 | 操作系统提供更高级的抽象 46 | 47 | 1. 锁、信号等 48 | 49 | 锁是一个抽象的数据结构 50 | 51 | 1. 一个二进制的状态 锁定和解锁 52 | 53 | test-and-set 测试和置位 54 | 55 | - 从内存读取值 56 | - 测试值是否为1 57 | - 内存值设置为1 58 | 59 | -------------------------------------------------------------------------------- /操作系统/信号量.md: -------------------------------------------------------------------------------- 1 | ## 信号量 2 | 3 | 信号量是一个整形,一个p操作,信号量减一, 4 | 5 | v操作,加1,唤醒一个等待的P操作。 6 | 7 | 信号量是一个整数 8 | 9 | 信号量一个受保护的变量。 10 | 11 | - 初始化完成后,唯一改变一个信号量的值的办法就是通过P()和v 12 | - 操作必须是原子操作 13 | 14 | P操作能够阻塞,V操作不会阻塞 15 | 16 | 我们假定信号量是公平的。FIFO 17 | 18 | 两种类型的信号量。 19 | 20 | - 二进制的信号量 0 或1 21 | - 一般计数信号量。 可以相互取任何非负值 22 | 23 | 信号量在两个方面 24 | 25 | - 互斥量 26 | - 条件同步 27 | 28 | 消息队列,使用互斥。 29 | 30 | ### 信号量的实现 31 | 32 | 需要一个整型变量,和一个等待队列。 33 | 34 | - 禁止中断 35 | - 原子指令。 36 | 37 | 信号量用途 38 | 39 | - 互斥和条件同步 40 | - 等待条件是独立的互斥 41 | 42 | 读、开发代码比较困难 43 | 44 | 容易出错。 45 | 46 | 不能处理死锁问题 -------------------------------------------------------------------------------- /操作系统/操作系统.md: -------------------------------------------------------------------------------- 1 | ## 操作系统 2 | 3 | 操作一个控制软件,管理应用程序,为应用程序提供服务,资源管理。管理CPU等硬件 4 | 5 | 操作系统把CPU抽象成**进程**,硬盘抽象成**文件**,内存抽象成**地址空间**。 6 | 7 | 操作系统面向硬件。在硬件之上。应用程序之下。 8 | 9 | 在操作系统层次的软件。面向应用程序的属于shell(外壳)。面向硬件的kernel(内核) 10 | 11 | **操作系统内部组件**。 12 | 13 | - CPU调度 14 | - 物理内存管理 15 | - 虚拟内存管理 16 | - 文件系统管理 17 | - 中断处理和设备驱动 18 | 19 | **操作系统特征** 20 | 21 | - **并发** 22 | - 计算机同时运行多个运行的程序 23 | - **共享** 24 | - 互斥共享 25 | - 利用多通道设计技术,虚拟技术 26 | - **异步** (程序的执行不是一贯到底,向前推进的速度不可预知。)只要运行环境下相同,os保证运行的结果也要相同。 27 | 28 | 并发在一段时间内,运行多个 程序。 29 | 30 | 并行是在一个时间点上运行多个程序。(多核) 31 | 32 | 33 | 34 | 操作系统融合了程序设计语言、数据结构、算法、计算机体系结构、操作系统概念和原理 35 | 36 | 操作系统需要良好的管理硬件,合理的资源分配。 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /操作系统/文件系统.md: -------------------------------------------------------------------------------- 1 | 文件:文件系统中一个单元的相关数据在操作系统中的抽象。 2 | 3 | 文件系统:一种用于持久存储的系统抽象。 4 | 5 | 分配文件磁盘空间。 6 | 7 | - 管理文件块 8 | - 管理空闲空间 9 | - 分配算法 10 | 11 | 管理文件集合 12 | 13 | - 定位文件和内容 14 | - 命名 通过名字找到文件 15 | - 分层文件系统 目录结构 16 | 17 | 提供的便利和特征 18 | 19 | - 保护 保护数据安全 20 | - 可靠性、持久性 保持文件的持久发生崩溃。 21 | 22 | 文件属性 23 | 24 | 名字、类型、位置、大小、保护、创建时间、最近修改时间 25 | 26 | 文件头 27 | 28 | 存储元数据中保持每个文件的内容。 29 | 30 | 31 | 32 | ## 文件描述符 33 | 34 | 打开一个文件,会返回一个文件描述符,整型数。 35 | 36 | 文件描述符 对应每个表中的index、 37 | 38 | 管理打开文件 39 | 40 | - 文件指针。指向最近一次的读写位置。 41 | - 文件打开的计数 记录文件打开的次数 42 | - 文件磁盘位置 缓存数据访问信息 43 | - 访问权限 每个程序访问模式信息 44 | 45 | 46 | 47 | ### 用户视图 48 | 49 | 持久的数据结构 50 | 51 | ### 系统视图 52 | 53 | 字节的集合。 54 | 55 | ### 操作系统视角 56 | 57 | 块的集合、块的大小、在unix 块的大小是4kb 58 | 59 | -------------------------------------------------------------------------------- /操作系统/管程.md: -------------------------------------------------------------------------------- 1 | ## 管程 2 | 3 | 目的:分离互斥、条件同步的关注。 4 | 5 | 什么是管程? 6 | 7 | - 一个锁。指定临界区 8 | - 0或者多个条件变量。等待、通知信号量用于管理并发访问共享数据 9 | 10 | -------------------------------------------------------------------------------- /操作系统/线程.md: -------------------------------------------------------------------------------- 1 | ## 线程 2 | 3 | 每个进程被分配一个时间段,称作它的**时间片**,即该进程允许运行的时间。如果在时间片结束时进程还在运行,则CPU将被剥夺并分配给另一个进程。如果进程在时间片结束前阻塞或结束,则CPU当即进行切换。调度程序所要做的就是维护一张就绪进程列表,当进程用完它的时间片后,它被移到队列的末尾 4 | 5 | 6 | 7 | 线程是进程中的一条执行流程。 8 | 9 | 从资源组合的角度,进程把一组相关的资源组合起来,构成了一个资源环境,(代码段,数据段)等 10 | 11 | 从运行的角度,代码在这个资源平台上的一条执行执行流程(线程)。 12 | 13 | 线程包括(pc、sp、state) 14 | 15 | 线程的优点: 16 | 17 | - 一个进程可以同时存在多个线程 18 | - 各个线程之间可以并发执行 19 | - 各个线程之间可以共享地址空间和文件资源 20 | 21 | 线程的缺点 22 | 23 | - 一个线程崩溃,导致进程退出 24 | 25 | 26 | 27 | ### 线程实现 28 | 29 | 1. 用户线程 用户空间实现 30 | 31 | posix pthread 32 | 33 | 操作系统看不到的线程。由运行库管理, 34 | 35 | 36 | 2. 内核线程 37 | 38 | windows api 39 | 40 | 操作系统管理的线程 41 | 42 | 3. 轻进程 43 | 44 | 内核支持的用户线程,一个进程可以有多个轻量进程,每个量级进程由一个单独内核线程来支持。 45 | 46 | 用户线程和内核线程对应 47 | 48 | - 1对1 49 | - 多对1 50 | - 多对多 51 | 52 | TCB(thread control block) 线程控制块。线程的调度,用户库实现。 53 | 54 | 每个进程需要的自己的线程控制块列表,跟踪记录它的各个线程的状态 信息。 55 | 56 | 57 | 58 | 用户线程缺点:一个线程发起系统调用而被阻塞,整个进程在等待。 59 | 60 | 内核线程:是在操作系统的内核当中实现的一种线程机制,由操作系统的内核来完成线程的创建、终止和管理。 61 | 62 | -------------------------------------------------------------------------------- /操作系统/线程同步.md: -------------------------------------------------------------------------------- 1 | 原子操作 2 | 3 | 原子操作是指一次不存在任何中断或失败的执行, 4 | 5 | - 该操作成功结束 6 | - 根本没有执行 7 | - 并且不应该发生任何部分执行的状态 8 | 9 | 10 | 11 | ### 临界区 12 | 13 | 临界区是进程中一段需要访问共享资源并且当另一个进程处于相应代码区域时便不会被执行的代码区域。 14 | 15 | ### 互斥 16 | 17 | 当一个进程处于临界区并访问共享资源的时候,没有其他进程会处于临界区并且访问任何相同的共享资源。 18 | 19 | ### 死锁 20 | 21 | 两个以上的进程,在相互等待特定的任务,而最终没法将自身任务进行下去、 22 | 23 | ### 饥饿 24 | 25 | 一个可执行的进程,被调度器持续忽略,到最后处于可执行,但是却不会被执行。 26 | 27 | 28 | 29 | 互斥: 同一个时间临界区最多存在一个线程或进程 30 | 31 | process:如果一个线程想进入临界区,那么会前进 32 | 33 | 有限等待:等待的时间是有限。 34 | 35 | 无忙等待:一个进程在等待进入临界区,在进入之前可以会挂起 -------------------------------------------------------------------------------- /操作系统/经典同步问题.md: -------------------------------------------------------------------------------- 1 | ### 读写问题 2 | 3 | 多个并发进程的数据集共享 4 | 5 | - 读者 只读数据集 他们不执行任何更新 6 | - 写者,可以读取和写入 7 | 8 | 共享数据 9 | 10 | - 数据集 11 | - 信号量countmutex 初始化1 12 | - 信号量writemutex初始化为1 13 | 14 | 15 | 16 | 至于谁优先的问题,主要从以下两个方面来判断: 17 | 18 | ​ 1、当优先级低的进程获得临界区时,高优先级进程能从低优先级进程中抢得临界区的访问权 19 | 20 | ​ 2、当优先级高的进程在访问临界区时,低优先级进程必须等待,直到高优先级全部访问完才有机会访问临界区 21 | 22 | 可以将所有读者和所有写者分别存于一个读者等待队列和一个写者等待队列中,每当读允许时,就从读者队列中释放一个或多个读者线程进行读操作; 23 | 当写允许时,就从写者队列中释放一个写者线程进行写操作。 24 |   读者优先。读者优先指的是除非有写者在写文件,否则读者不需要等待。所以可以用一个整数变量Read_count记录当前的读者数目,用于确定是否需要释放正在等待的写者进程(当Read_count=0时,表明所有的读者读完,需要释放写者等待队列中的一个写者)。每当一个读者开始读文件时,必须修改Read_count变量。因此需要一个互斥对象mutex来实现对全局变量Read_count修改时的互斥。 25 |   另外,为了实现读-写互斥,需要增加一个临界区对象Write。当写者发出写请求时,必须申请临界区对象的所有权。通过这种方法,可以实现读-写互斥,当Read_count=1时(即第一个读者到来时),读者线程也必须申请临界区对象的所有权。 26 |   当读者拥有临界区的所有权时,写者阻塞在临界区对象Write上。当写者拥有临界区的所有权时,第一个读者判断完”Read_count==1”后阻塞在Write上,其余的读者由于等待对Read_count的判断,阻塞在mutex上。 27 |   写者优先。写者优先与读者优先相类似。不同之处在于一旦一个写者到来,它应该尽快对文件进行写操作,如果有一个写者在等待,则新到来的读者不允许进行读操作。为此应当填加一个整形变量Write_count,用于记录正在等待的写者的数目,当Write_count=0时,才可以释放等待的读者线程队列 -------------------------------------------------------------------------------- /操作系统/进程控制.md: -------------------------------------------------------------------------------- 1 | ## 进程控制 2 | 3 | 停止当前的运行进程,并且调度其他进程。 4 | 5 | - 必须在切换之前存储部分进程的上下文 6 | - 必须能够在之后恢复他们。 7 | - 必须迅速切换 8 | 9 | 上下文:程序运行需要的资源的集合 10 | 11 | 存储上下文 12 | 13 | 寄存器、cpu状态 14 | 15 | 操作系统为活跃继承准备进程控制块,将进程控制块放置一个合适的队列。 16 | 17 | 就绪队列、等待队列、僵尸队列。 18 | 19 | exec 加载一个不同的程序, 并执行新的程序。 20 | 21 | 如果调用成功,代码段、堆栈被覆盖 22 | 23 | 24 | 25 | fork的开销 26 | 27 | - 对子进程分配内存 28 | - 复制父进程的内存和cpu寄存器到子进程 29 | - 开销大 30 | 31 | 在99%的清空下,我们调用fork之后,直接调用exec 32 | 33 | - 在fork 操作内存复制是没有用的 34 | - 子进程将关闭打开的文件 35 | - 开销高 36 | 37 | vfork 38 | 39 | - 一个创建进程的系统调用,不需要创建一个同样的内存映像 40 | - 子进程应该不立即调用exec 41 | - cow 42 | 43 | 44 | 45 | wait 系统调用,是被父进程来等待子进程的结束, 46 | 47 | - 一个子进程向父进程返回一个值, 48 | 49 | wait系统调用担任的角色 50 | 51 | - 它使父进程去睡眠等待子进程的结果 52 | - 当一个子进程调用exit,操作系统解锁父进程, 53 | - 如果有父进程的僵尸等待,wait立即返回其中一个值、 54 | - 释放内存 55 | - 关闭所有打开的文件 56 | - 检查父进程是存存活。 57 | 58 | 进程结束执行之后,调用exit() 59 | 60 | -------------------------------------------------------------------------------- /操作系统/进程通信.md: -------------------------------------------------------------------------------- 1 | ## IPC 2 | 3 | 直接通信 4 | 5 | 进程必须正确的命名对象 6 | 7 | - send (p,message) 发送信息到进程p 8 | - receive (q,message)从进程q接受消息 9 | 10 | 通信链路的属性 11 | 12 | - 只有进程共享一个共同的消息队列,才建立链路 13 | - 链路可以与许多进程相关联。 14 | 15 | 间接通信 16 | 17 | - 创建一个新的消息队列 18 | - 通过消息队列发送和接收消息 19 | - 销毁消息队列 20 | 21 | 消息传递可以是阻塞或者非阻塞的。 22 | 23 | ### 信号 24 | 25 | signal 软件中断通知事件处理 26 | 27 | 信号是操作系统完成的。 28 | 29 | - 注册一个信号handle 当产生信号的时候调用函数 30 | 31 | 32 | 33 | ### 管道 34 | 35 | 子进程从父进程继承文件描述符。 0 1 2 36 | 37 | 管道的buffer是有限的。满了会阻塞。 38 | 39 | 40 | 41 | ### 消息队列 42 | 43 | 消息队列,传递数据。 44 | 45 | 管道是父进程帮子进程建立的通道 46 | 47 | 消息队列,按FIFO来管理消息。 48 | 49 | message 作为一个字节序列储存。 50 | 51 | message queues 消息队列。 52 | 53 | 也是有buffer。 54 | 55 | ### 共享内存 56 | 57 | 直接通信的方式。两个进程有一个特殊的空间,是两个进程,都可以访问的。 58 | 59 | 快速、方便地共享数据。 60 | 61 | 必须同步数据访问。 62 | 63 | ### socket通信 64 | 65 | -------------------------------------------------------------------------------- /整合资源.md: -------------------------------------------------------------------------------- 1 | ## 编程语言 2 | 3 | - PHP 4 | - Python 5 | - Golang 6 | - HTML 7 | - CSS 8 | - JavaScript 9 | - C 10 | 11 | ## 工具软件 12 | 13 | - PhpStorm 14 | - Sublime Text 3 15 | - Microsoft VS Code 16 | - Git、SVN 17 | - SourceTree、TortoiseSVN 18 | - Fiddler、WinSCP、Xshell、Wireshark 19 | - Typora、Navicat 20 | - PHPStudy 21 | 22 | ## 框架 23 | 24 | - ThinkPHP 25 | 26 | - laravel 27 | 28 | - Yii 29 | 30 | - CI 31 | 32 | - Swoole 33 | 34 | ​ 35 | 36 | -------------------------------------------------------------------------------- /算法和数据结构/1.数学知识.md: -------------------------------------------------------------------------------- 1 | ## 数学知识回顾 2 | 3 | 1. 指数 4 | 5 | ```math 6 | X^AX^B = X^{A+B} 7 | 8 | \frac{X^A }{X^B} = X^{A-B} 9 | 10 | 11 | (X^A)^B = X^{AB} 12 | 13 | X^A+X^A = 2X^A 14 | 15 | 2^N+2^N = 2^{N+1} 16 | 17 | ``` 18 | 19 | 2. 对数 20 | 21 | 22 | 默认都是以2为底 23 | 24 | ```math 25 | 26 | 2^X = A 27 | 28 | logA = X 29 | 30 | \log_{A}B = \frac{\log_{C}B}{\log_{C}A} ;C>0 31 | 32 | logAB = logA+logB 33 | 34 | logA
3 排序3,6 8 | 9 | 第二趟。从4开始 认为前面的是排号的。6>4 将6后移动,4再跟3比较4>3 位置不变。3,4,6 10 | 11 | 第三趟,将设3,4,6已经是拍好的。用2跟6比较。这趟的结果是2,3,4,6 12 | 13 | 第四趟 1,2,3,4,6 14 | 15 | 平均时间复杂度:O(n2) 16 | 17 | 空间复杂度:O(1) (用于记录需要插入的数据) 18 | 19 | 稳定性:稳定 20 | 21 | 22 | 通过相互交换两个元素位置的算法平均需要O(n^2) 23 | ```c 24 | 25 | 26 | 27 | int *insertSort(int arr[]) 28 | { 29 | int i,j; 30 | for(i=1;i=0 && temp < arr[j];j--){ 34 | 35 | arr[j+1]= arr[j]; 36 | 37 | } 38 | arr[j+1] = temp; 39 | } 40 | return arr; 41 | 42 | } 43 | 44 | 45 | ``` 46 | -------------------------------------------------------------------------------- /算法和数据结构/6.树.md: -------------------------------------------------------------------------------- 1 | ## 树 2 | 3 | 4 | 5 | 对于大量数据进行查找的时候,链表查找太慢。我们使用二分查找树,它的时间复杂度是O 6 | 7 | ![image](http://images.cnblogs.com/cnblogs_com/ajayumi/ProgramImage/2009050402.jpg) 8 | 9 | 没有上节点的节点就是根节点。如图A.B、C成为A的子节点。一棵树有且只有一个根节点。 10 | 11 | 没有子节点的节点 叫做叶片 如图 #就是一个叶片 12 | 13 | ![image](http://img.blog.csdn.net/20160320160302975) 14 | 15 | 树是一种“一对多”的数据结构,是n(n≥0)个结点的有限集,其中n=0时称为空树 16 | 17 | 树满足的一些性质和概念 18 | 19 | - n>0时,根结点唯一 20 | - n>1时,除去根结点的其他结点构成若干个互不相交的有限集T1,T2...,其中每一个集合又是一棵树,称为根的子树 21 | - 结点拥有的子树数称为结点的度(Degree),度为0的结点称为叶子结点 22 | - 树的度是树内各结点的度的最大值 23 | - 结点的层数是从根开始定义起,根为第一层,根的孩子是第二层,以此类推。树中结点的最大层次称为树的深度(Depth)或高度 24 | - 如果各子树看成从左至右不可互换的,则称为有序树,否则为无序树 25 | - 森林是互不相交的树的集合,某个结点的子树可以看做是森林 26 | 27 | 28 | ### 二叉树 29 | 30 | ![image](http://images.cnitblog.com/i/497634/201403/270929530778327.jpg) 31 | 二叉树是每个节点最多有两个子树的树结构。它有五种基本形态:二叉树可以是空集;根可以有空的左子树或右子树;或者左、右子树皆为空 32 | 33 | ### 二叉查找树 34 | 35 | 二叉查找树(Binary Search Tree),又被称为二叉搜索树。设x为二叉查找树中的一个结点,x节点包含关键字key,节点x的key值记为key[x]。如果y是x的左子树中的一个结点,则key[y] <= key[x];如果y是x的右子树的一个结点,则key[y] >= key[x]。 36 | 37 | ![image](http://images.cnitblog.com/i/497634/201403/270932052801072.jpg) 38 | 39 | 在二叉查找树中: 40 | - (01) 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 41 | - (02) 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 42 | - (03) 任意节点的左、右子树也分别为二叉查找树。 43 | - (04) 没有键值相等的节点(no duplicate nodes)。 44 | - 45 | 46 | ### AVL树 47 | 48 | AVL是自平衡二叉查找树,也被称为高度平衡树。它的特点是任意一个节点的两个子树的高度差1. 49 | 50 | ![image](http://images.cnitblog.com/i/497634/201403/281623404229547.jpg) 51 | 52 | 53 | 左侧就是avl树,右侧不是(右侧的7的右节点的高度为1,而2的节点的高度是3); 54 | 55 | AVL树的查找、插入和删除在平均和最坏情况下都是O(logn)。 -------------------------------------------------------------------------------- /算法和数据结构/9.排序(冒泡排序).md: -------------------------------------------------------------------------------- 1 | ## 冒泡排序 2 | 3 | 冒泡是一个最基本的排序。原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换, 4 | 5 | 这样一趟过去后,最大或最小的数字被交换到了最后一位。然后重复以上的操作。是一个稳定的排序,时间复杂度为O(n^2) 6 | 7 | 算法实现如下 8 | 9 | 10 | ``` 11 | #include 12 | #include 13 | 14 | int length; 15 | int *bubble_sort(int arr[]) 16 | { 17 | int i,j; 18 | for (i=0;iarr[j+1]) { 23 | int temp = arr[j]; 24 | arr[j] = arr[j+1]; 25 | arr[j+1] = temp; 26 | } 27 | } 28 | 29 | } 30 | return arr; 31 | } 32 | 33 | int main(){ 34 | 35 | int arr[] = {3,1,4,7,2,9,8}; 36 | length = sizeof(arr)/sizeof(arr[0]); 37 | bubble_sort(arr); 38 | int i; 39 | for(i=0;i 为了更清晰地理解工厂方法模式,需要先引入两个概念: 6 | > 7 | > - **产品等级结构** :产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。 8 | > - **产品族** :在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中。 9 | 10 | - 当系统所提供的工厂所需生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构中属于不同类型的具体产品时需要使用抽象工厂模式。 11 | 12 | - 抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态。 13 | 14 | - 抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建 。当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、有效率。 15 | 16 | 简单的白话理解:抽象工厂比工厂方法可以创造不同的产品镞的产品。比如一个工厂可以创建电视机,也能创建冰箱。工厂方法 一个工厂只能创建一个产品。 17 | 18 | ### 模式结构 19 | 20 | 抽象工厂模式包含如下角色: 21 | 22 | - AbstractFactory:抽象工厂 23 | - ConcreteFactory:具体工厂 24 | - AbstractProduct:抽象产品 25 | - Product:具体产品 26 | 27 | ![../_images/AbatractFactory.jpg](http://design-patterns.readthedocs.io/zh_CN/latest/_images/AbatractFactory.jpg) -------------------------------------------------------------------------------- /设计模式/设计模式笔记/04单例模式md.md: -------------------------------------------------------------------------------- 1 | ## 单例模式 2 | 3 | 单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。 4 | 5 | 单例模式的要点有三个:一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。单例模式是一种对象创建型模式。单例模式又名单件模式或单态模式。 6 | 7 | ![../_images/Singleton.jpg](http://design-patterns.readthedocs.io/zh_CN/latest/_images/Singleton.jpg) 8 | 9 | 10 | 11 | ```php 12 | class Singleton { 13 | private static $_instance; 14 | public static function getInstance(){ 15 | if(self::$_instance == null) { 16 | self::$_instance = new Singleton(); 17 | } 18 | return self::$_instance; 19 | } 20 | } 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /设计模式/设计模式笔记/05观察者模式.md: -------------------------------------------------------------------------------- 1 | ## 观察者模式 2 | 3 | 观察者定义了对象之间的依赖关系,当一个对象发生变化,其依赖的对象就会发生变化。 4 | 5 | 观察者模式需要以下的角色。 6 | 1. Subject: 目标 7 | 2. ConcreteSubject: 具体目标 8 | 3. Observer: 观察者 9 | 4. ConcreteObserver: 具体观察者 10 | 11 | ![../_images/Obeserver.jpg](http://design-patterns.readthedocs.io/zh_CN/latest/_images/Obeserver.jpg) 12 | 13 | -------------------------------------------------------------------------------- /设计模式/设计模式笔记/06建造者模式.md: -------------------------------------------------------------------------------- 1 | # 建造者模式 2 | 3 | 造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 4 | 5 | 建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。建造者模式属于对象创建型模式。根据中文翻译的不同,建造者模式又可以称为生成器模式。 6 | 7 | 简单白话解释:建造者就是把一大堆对象组合一起,形成一个新的对象。比如我们要造一个车的对象,但是这个车有方向盘,轮胎,发动机等。我们需要创建各个不同的对象,但是我们只要这个车对象,不需要关心底下的那些细节。 8 | 9 | 建造者模式包含如下角色: 10 | 11 | - Builder:抽象建造者 12 | - ConcreteBuilder:具体建造者 13 | - Director:指挥者 14 | - Product:产品角色 15 | 16 | ![../_images/Builder.jpg](http://design-patterns.readthedocs.io/zh_CN/latest/_images/Builder.jpg) 17 | 18 | -------------------------------------------------------------------------------- /设计模式/设计模式笔记/code/abstractFactory/AbstractFactory.php: -------------------------------------------------------------------------------- 1 | product->add("door",new ProductA()); 17 | 18 | } 19 | 20 | public function createB() { 21 | return new ProductB(); 22 | 23 | } 24 | 25 | public function createC() { 26 | 27 | } 28 | 29 | public function getProduct() { 30 | 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /设计模式/设计模式笔记/code/builder/Director.php: -------------------------------------------------------------------------------- 1 | createA(); 16 | $build->createB(); 17 | $build->createC(); 18 | return $build->getProduct(); 19 | } 20 | } -------------------------------------------------------------------------------- /设计模式/设计模式笔记/code/builder/ProductA.php: -------------------------------------------------------------------------------- 1 | color = $color; 17 | } 18 | } -------------------------------------------------------------------------------- /设计模式/设计模式笔记/code/factoryMethod/FactoryMethod.php: -------------------------------------------------------------------------------- 1 | color= 'black'; 14 | } 15 | } -------------------------------------------------------------------------------- /设计模式/设计模式笔记/code/factoryMethod/test.php: -------------------------------------------------------------------------------- 1 | _observers[$key])) { 13 | $this->_observers[$key] = $observer; 14 | } 15 | } 16 | 17 | public function detach(Observer $observer) { 18 | 19 | $key = spl_object_hash($observer); 20 | 21 | if(!empty($this->_observers[$key])) { 22 | unset($this->_observers[$key]); 23 | } 24 | 25 | } 26 | 27 | public function notify() { 28 | if(!empty($this->_observers)) { 29 | foreach ($this->_observers as $observer) { 30 | $observer->update(); 31 | } 32 | } 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /设计模式/设计模式笔记/code/observer/Observer.php: -------------------------------------------------------------------------------- 1 |