├── .all-contributorsrc ├── .editorconfig ├── .github ├── FUNDING.yml └── workflows │ └── lint-md.yml ├── .gitmodules ├── .lintmdrc ├── .minttyrc.md ├── .vimrc.md ├── CHANGELOG.md ├── Chrome.md ├── Docs └── Images │ ├── MVC.png │ ├── Select-license.jpg │ ├── Vim-molokai.png │ ├── man-cn.png │ └── the-relationship-between-design-patterns.jpg ├── Frontend ├── CSS.md ├── HTML.md ├── JSON.md ├── Javascript.md ├── Less.md ├── Sass.md ├── XML.md ├── YAML.md └── jQuery.md ├── Git ├── Git.md ├── git-commit-message-change-log.md └── 常用Git命令清单.md ├── Go ├── Go.md ├── Golang.md ├── golang.go └── hello-world.go ├── LICENSE ├── Linux ├── C++.md ├── C.md ├── Java.md ├── Vim.md ├── bash.md └── the-art-of-command-line.md ├── Lua └── Lua.md ├── MongoDB └── SQL到Mongo的对应表.md ├── MySQL ├── MySQL常用函数汇总.md ├── MySQL数据库开发的三十六条军规.md ├── MySQL数据库设计规范.md ├── 数据类型.md └── 语法.md ├── PHP ├── PHP.md ├── PHP7.0至PHP7.3的新特性.md ├── PHPUnit.md ├── PHP学习路线图.md ├── PHP工具包.md ├── PHP常用函数.md ├── PHP常量.md ├── PHP的SPL-Exception.md └── php.php ├── PhpStorm.md ├── Python ├── Python.md └── Python3.md ├── README.md ├── Redis └── Redis.md ├── Ruby └── Ruby.md ├── Rust ├── Rust.md └── hello-world.rs ├── Select-license.md ├── Shell.md ├── Sublime.md ├── Useful-website.md ├── Vscode.md ├── Vue ├── demo.html └── vue-base-demo │ ├── css │ └── index.css │ ├── detail.html │ ├── images │ └── icon_fada.png │ ├── js │ └── data.js │ └── list.html ├── _config.yml ├── iOS.md ├── iOS ├── app.json └── app.sqlite ├── mac-man-cn.md ├── macOS.md ├── 《代码整洁之道》.md ├── 应用代码分层.md ├── 正则表达式不要背.md ├── 设计模式的七大原则.md └── 设计模式(45种).md /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "contributors": [ 8 | { 9 | "login": "gaoyongfu", 10 | "name": "渊虹", 11 | "avatar_url": "https://avatars2.githubusercontent.com/u/32188852?v=4", 12 | "profile": "https://github.com/gaoyongfu", 13 | "contributions": [ 14 | "doc" 15 | ] 16 | } 17 | ], 18 | "contributorsPerLine": 7, 19 | "projectName": "notes", 20 | "projectOwner": "guanguans", 21 | "repoType": "github", 22 | "repoHost": "https://github.com" 23 | } 24 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = false 10 | 11 | [*.{vue,js,scss}] 12 | charset = utf-8 13 | indent_style = space 14 | indent_size = 2 15 | end_of_line = lf 16 | insert_final_newline = true 17 | trim_trailing_whitespace = true 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | patreon: guanguans # Replace with a single Patreon username 4 | custom: # Replace with a single custom sponsorship URL 5 | -------------------------------------------------------------------------------- /.github/workflows/lint-md.yml: -------------------------------------------------------------------------------- 1 | name: lint markdown 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | lint-markdown: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@v2 11 | 12 | - name: lint-md-github-action 13 | uses: lint-md/github-action@v0.1.1 14 | with: 15 | configFile: .lintmdrc 16 | failOnWarnings: false 17 | files: ./ ./*/ 18 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "design-patterns-for-humans-cn"] 2 | path = design-patterns-for-humans-cn 3 | url = https://github.com/guanguans/design-patterns-for-humans-cn.git 4 | [submodule "awesome-mongodb-cn"] 5 | path = awesome-mongodb-cn 6 | url = https://github.com/guanguans/awesome-mongodb-cn.git 7 | -------------------------------------------------------------------------------- /.lintmdrc: -------------------------------------------------------------------------------- 1 | { 2 | "excludeFiles": [ 3 | "src/", 4 | "tests/", 5 | "vendor/" 6 | ], 7 | "rules": { 8 | "no-empty-code": 1, 9 | "no-long-code": [ 10 | 2, 11 | { 12 | "length": 256, 13 | "exclude": [ 14 | "dot" 15 | ] 16 | } 17 | ] 18 | } 19 | } -------------------------------------------------------------------------------- /.minttyrc.md: -------------------------------------------------------------------------------- 1 | # .minttyrc 2 | 3 | ## 配置 4 | 5 | ``` bash 6 | Black=39,40,34 7 | BoldBlack=117,113,94 8 | Red=249,38,114 9 | BoldRed=253,151,31 10 | Green=166,226,46 11 | BoldGreen=56,56,48 12 | Yellow=244,191,117 13 | BoldYellow=73,72,62 14 | Blue=102,217,239 15 | BoldBlue=165,159,133 16 | Magenta=174,129,255 17 | BoldMagenta=245,244,241 18 | Cyan=161,239,228 19 | BoldCyan=204,102,51 20 | White=248,248,242 21 | BoldWhite=249,248,245 22 | ``` 23 | 24 | ## 相关链接 25 | 26 | * [https://github.com/oumu/mintty-color-schemes](https://github.com/oumu/mintty-color-schemes) 27 | -------------------------------------------------------------------------------- /.vimrc.md: -------------------------------------------------------------------------------- 1 | # 一份简单的没有插件的 vim 配置 2 | 3 | ## molokai 主题 4 | 5 | 如果习惯 molokai 主题,前往[https://github.com/tomasr/molokai](https://github.com/tomasr/molokai) 6 | 7 | ![效果预览](./Docs/Images/Vim-molokai.png) 8 | 9 | ## .vimrc 10 | 11 | ``` bash 12 | " leader 13 | let mapleader = ',' 14 | let g:mapleader = ',' 15 | 16 | " syntax 17 | syntax on 18 | 19 | " history : how many lines of history VIM has to remember 20 | set history=2000 21 | 22 | " filetype 23 | filetype on 24 | " Enable filetype plugins 25 | filetype plugin on 26 | filetype indent on 27 | 28 | 29 | " base 30 | set nocompatible " don't bother with vi compatibility 31 | set autoread " reload files when changed on disk, i.e. via `git checkout` 32 | set shortmess=atI 33 | 34 | set magic " For regular expressions turn magic on 35 | set title " change the terminal's title 36 | set nobackup " do not keep a backup file 37 | 38 | set novisualbell " turn off visual bell 39 | set noerrorbells " don't beep 40 | set visualbell t_vb= " turn off error beep/flash 41 | set t_vb= 42 | set tm=500 43 | 44 | 45 | " show location 46 | set cursorcolumn 47 | set cursorline 48 | 49 | 50 | " movement 51 | set scrolloff=7 " keep 3 lines when scrolling 52 | 53 | 54 | " show 55 | set ruler " show the current row and column 56 | set number " show line numbers 57 | set nowrap 58 | set showcmd " display incomplete commands 59 | set showmode " display current modes 60 | set showmatch " jump to matches when entering parentheses 61 | set matchtime=2 " tenths of a second to show the matching parenthesis 62 | 63 | 64 | " search 65 | set hlsearch " highlight searches 66 | set incsearch " do incremental searching, search as you type 67 | set ignorecase " ignore case when searching 68 | set smartcase " no ignorecase if Uppercase char present 69 | 70 | 71 | " tab 72 | set expandtab " expand tabs to spaces 73 | set smarttab 74 | set shiftround 75 | 76 | " indent 77 | set autoindent smartindent shiftround 78 | set shiftwidth=4 79 | set tabstop=4 80 | set softtabstop=4 " insert mode tab and backspace use 4 spaces 81 | 82 | " NOT SUPPORT 83 | " fold 84 | set foldenable 85 | set foldmethod=indent 86 | set foldlevel=99 87 | let g:FoldMethod = 0 88 | map zz :call ToggleFold() 89 | fun! ToggleFold() 90 | if g:FoldMethod == 0 91 | exe "normal! zM" 92 | let g:FoldMethod = 1 93 | else 94 | exe "normal! zR" 95 | let g:FoldMethod = 0 96 | endif 97 | endfun 98 | 99 | " encoding 100 | set encoding=utf-8 101 | set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1 102 | set termencoding=utf-8 103 | set ffs=unix,dos,mac 104 | set formatoptions+=m 105 | set formatoptions+=B 106 | 107 | " select & complete 108 | set selection=inclusive 109 | set selectmode=mouse,key 110 | 111 | set completeopt=longest,menu 112 | set wildmenu " show a navigable menu for tab completion" 113 | set wildmode=longest,list,full 114 | set wildignore=*.o,*~,*.pyc,*.class 115 | 116 | " others 117 | set backspace=indent,eol,start " make that backspace key work the way it should 118 | set whichwrap+=<,>,h,l 119 | 120 | " if this not work ,make sure .viminfo is writable for you 121 | if has("autocmd") 122 | au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif 123 | endif 124 | 125 | " NOT SUPPORT 126 | " Enable basic mouse behavior such as resizing buffers. 127 | " set mouse=a 128 | 129 | 130 | " ============================ theme and status line ============================ 131 | 132 | " theme 133 | set background=dark 134 | colorscheme desert 135 | " colorscheme molokai 136 | " let g:molokai_original = 1 137 | " let g:rehash256 = 1 138 | 139 | 140 | " set mark column color 141 | hi! link SignColumn LineNr 142 | hi! link ShowMarksHLl DiffAdd 143 | hi! link ShowMarksHLu DiffChange 144 | 145 | " status line 146 | set statusline=%<%f\ %h%m%r%=%k[%{(&fenc==\"\")?&enc:&fenc}%{(&bomb?\",BOM\":\"\")}]\ %-14.(%l,%c%V%)\ %P 147 | set laststatus=2 " Always show the status line - use 2 lines for the status bar 148 | 149 | 150 | " ============================ specific file type =========================== 151 | 152 | autocmd FileType python set tabstop=4 shiftwidth=4 expandtab ai 153 | autocmd FileType ruby set tabstop=2 shiftwidth=2 softtabstop=2 expandtab ai 154 | autocmd BufRead,BufNew *.md,*.mkd,*.markdown set filetype=markdown.mkd 155 | 156 | autocmd BufNewFile *.sh,*.py exec ":call AutoSetFileHead()" 157 | function! AutoSetFileHead() 158 | " .sh 159 | if &filetype == 'sh' 160 | call setline(1, "\#!/bin/bash") 161 | endif 162 | 163 | " python 164 | if &filetype == 'python' 165 | call setline(1, "\#!/usr/bin/env python") 166 | call append(1, "\# encoding: utf-8") 167 | endif 168 | 169 | normal G 170 | normal o 171 | normal o 172 | endfunc 173 | 174 | autocmd FileType c,cpp,java,go,php,javascript,puppet,python,rust,twig,xml,yml,perl autocmd BufWritePre :call StripTrailingWhitespaces() 175 | fun! StripTrailingWhitespaces() 176 | let l = line(".") 177 | let c = col(".") 178 | %s/\s\+$//e 179 | call cursor(l, c) 180 | endfun 181 | 182 | " ============================ key map ============================ 183 | 184 | nnoremap k gk 185 | nnoremap gk k 186 | nnoremap j gj 187 | nnoremap gj j 188 | 189 | map j 190 | map k 191 | map h 192 | map l 193 | 194 | nnoremap :set nu! nu? 195 | nnoremap :set list! list? 196 | nnoremap :set wrap! wrap? 197 | set pastetoggle= " when in insert mode, press to go to 198 | " paste mode, where you can paste mass data 199 | " that won't be autoindented 200 | au InsertLeave * set nopaste 201 | nnoremap :exec exists('syntax_on') ? 'syn off' : 'syn on' 202 | 203 | " kj 替换 Esc 204 | inoremap kj 205 | 206 | " Quickly close the current window 207 | nnoremap q :q 208 | " Quickly save the current file 209 | nnoremap w :w 210 | 211 | " select all 212 | map sa ggVG" 213 | 214 | " remap U to for easier redo 215 | nnoremap U 216 | 217 | " Swap implementations of ` and ' jump to markers 218 | " By default, ' jumps to the marked line, ` jumps to the marked line and 219 | " column, so swap them 220 | nnoremap ' ` 221 | nnoremap ` ' 222 | 223 | " switch # * 224 | " nnoremap # * 225 | " nnoremap * # 226 | 227 | "Keep search pattern at the center of the screen." 228 | nnoremap n nzz 229 | nnoremap N Nzz 230 | nnoremap * *zz 231 | nnoremap # #zz 232 | nnoremap g* g*zz 233 | 234 | " remove highlight 235 | noremap / :nohls 236 | 237 | "Reselect visual block after indent/outdent.调整缩进后自动选中,方便再次操作 238 | vnoremap < >gv 240 | 241 | " y$ -> Y Make Y behave like other capitals 242 | map Y y$ 243 | 244 | "Map ; to : and save a million keystrokes 245 | " ex mode commands made easy 用于快速进入命令行 246 | nnoremap ; : 247 | 248 | " Shift+H goto head of the line, Shift+L goto end of the line 249 | nnoremap H ^ 250 | nnoremap L $ 251 | 252 | " save 253 | cmap w!! w !sudo tee >/dev/null % 254 | 255 | " command mode, ctrl-a to head, ctrl-e to tail 256 | cnoremap 257 | cnoremap 258 | cnoremap 259 | cnoremap 260 | ``` 261 | 262 | ## 原配置地址 263 | 264 | * [https://github.com/wklken/vim-for-server](https://github.com/wklken/vim-for-server) 265 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 1.0.0 (2018-11-12) 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Chrome.md: -------------------------------------------------------------------------------- 1 | # Chrome 2 | 3 | ## 插件 4 | 5 | * **[谷歌访问助手【强烈推荐】](https://chrome.google.com/webstore/detail/%E8%B0%B7%E6%AD%8C%E8%AE%BF%E9%97%AE%E5%8A%A9%E6%89%8B/gocklaboggjfkolaknpbhddbaopcepfp?utm_source=chrome-app-launcher-info-dialog)** - 一键安装,无需其他配置,即可访问谷歌。 6 | * **[扩展管理器(Extension Manager)【强烈推荐】](https://chrome.google.com/webstore/detail/extension-manager/gjldcdngmdknpinoemndlidpcabkggco)** - 一键管理所有扩展,快速开启/禁用、批量闪电管理,智能排序,右键卸载、锁定、选项配置,角标提醒,大小布局随心配。 7 | * **[Tampermonkey【强烈推荐】](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo)** - 插件中的超级插件,不解释,最受欢迎的用户脚本管理器,拥有超过 1000 万用户。 8 | * **[Click&Clean【强烈推荐】](https://chrome.google.com/webstore/detail/clickclean/ghgabhipcejejjmhhchfonmamedcbeod)** - 很方便的浏览器的缓存、下载文件、内存、cookie、插件等各种管理。 9 | * **[Checker Plus for Gmail™【强烈推荐】](https://chrome.google.com/webstore/detail/checker-plus-for-gmail/oeopbcgkkoapgobdbedcemjljbihmemj)** - 方便地接受邮件通知、查看、收听或删除邮件,并且支持多账户,语音播放。 10 | * **[OneTab【强烈推荐】](https://chrome.google.com/webstore/detail/onetab/chphlpgkkbolifaimnlloiipkdnihall)** - 当您发现自己有太多的标签页时,单击 OneTab 图标,将所有标签页转换成一个列表。当您需要再次访问这些标签页时,可以单独或全部恢复它们。 11 | * **[ElasticSearch Head【强烈推荐】](https://chrome.google.com/webstore/detail/elasticsearch-head/ffmkiejjmecolpfloofpjologoblkegm)** - 界面化管理大名鼎鼎全文搜索引擎 [ElasticSearch](https://www.elastic.co/products/elasticsearch)的数据。 12 | * **[ImTranslator: 翻译,字典,声音](https://chrome.google.com/webstore/detail/imtranslator-translator-d/noaijdpnepcgjemiklgfkcfbkokogabh)** - 由于[划词翻译](https://chrome.google.com/webstore/detail/%E5%88%92%E8%AF%8D%E7%BF%BB%E8%AF%91/ikhdkkncnoglghljlkmcimlnlhkeamad?utm_source=chrome-ntp-icon)的谷歌翻译接口不能用了。找了这个做替代。发现比划词翻译还好用。 13 | * **[Infinity 新标签页(Pro)【强烈推荐】](https://chrome.google.com/webstore/detail/infinity-new-tab-pro/nnnkddnnlpamobajfibfdgfnbcnkgngh)** - 可能是 Chrome 浏览器上最好用的新标签页。 14 | * **[WEB 前端助手(FeHelper)【强烈推荐】](https://chrome.google.com/webstore/detail/web%E5%89%8D%E7%AB%AF%E5%8A%A9%E6%89%8Bfehelper/pkgccpejnmalmdinmhkkfafefagiiiad)** - FE 助手:包括字符串编解码、代码压缩、美化、JSON 格式化、正则表达式、时间转换工具、二维码生成与解码、编码规范检测、页面性能检测、页面取色、Ajax 接口调试。 15 | * **[LastPass: Free Password Manager【强烈推荐】](https://chrome.google.com/webstore/detail/lastpass-free-password-ma/hdokiejnpimakedhajhdlcegeplioahd)** - LastPass 密码管理器,保存你的密码,让你安全访问任何计算机和移动设备。 16 | * **[QPush - 从电脑快推文字到手机](https://chrome.google.com/webstore/detail/qpush-push-text-and-links/eccidpbmllnjfhhnjhaaopeeldnlokbi)** - QPush 是从电脑推送文字到 iPhone 上最方便的小工具,可以轻松推送文字或网页。只要三秒钟,推送超顺手! 17 | * **[Send Anywhere](https://chrome.google.com/webstore/detail/send-anywherefile-transfe/amjmjholfoknokffkiolahocokcaecnc)** - 发送和分享大文件。 18 | * **[简悦 - SimpRead【强烈推荐】](https://chrome.google.com/webstore/detail/simpread-reader-view/ijllcpnolfcooahcekpamkbidhejabll)** - 让你瞬间进入沉浸式阅读的 Chrome 扩展,类似 Safari 的阅读模式。 19 | * **[壹伴 · 小插件](https://chrome.google.com/webstore/detail/simpread-reader-view/ijllcpnolfcooahcekpamkbidhejabll)** - 简单好用的公众号效率工具。 20 | * **[Tidy Bookmarks](https://chrome.google.com/webstore/detail/tidy-bookmarks/bennikkpnelmfdiijpdclfincmnoabae)** - 对比了很多书签管理插件,最终选择了这个。 21 | * **[Adblock Plus【强烈推荐】](https://chrome.google.com/webstore/detail/adblock-plus/cfhdojbkjhnklbpkdaibdccddilifddb)** - 最受欢迎的广告拦截软件。 22 | * **[Download in IDM](https://chrome.google.com/webstore/detail/download-in-idm-internet/lmpemnebipihbcadlafaidjibohhfocn)** - 大名鼎鼎的[*idm*(internet download manager)](http://www.internetdownloadmanager.com/)的下载插件,需要安装 idm。 23 | * **[Wappalyzer【强烈推荐】](https://chrome.google.com/webstore/detail/wappalyzer/gppongmhjkpfnbhagpmjfkannfbllamg)** - 探测当前网页所使用的类库、框架和服务器环境。 24 | * **[Library Sniffer for Google Chrome](https://chrome.google.com/webstore/detail/library-sniffer-for-googl/fhhdlnnepfjhlhilgmeepgkhjmhhhjkh)** - 另一个探测当前网页所使用的类库、框架和服务器环境,个人喜欢 Wappalyzer。 25 | * **[BuiltWith Technology Profiler【强烈推荐】](https://chrome.google.com/webstore/detail/builtwith-technology-prof/dapjbgnjinbpoindlpdmhochffioedbn)** - 探测当前网页所有信息,相比 Wappalyzer 和 Library Sniffer for Google Chrome 探测的信息更为多。 26 | * **[Lighthouse](https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk)** - Lighthouse 是一款开源的自动化工具,用于改善 Web 应用程序的性能,质量和正确性,优化网站性能。 27 | * **[Image Downloader](https://chrome.google.com/webstore/detail/image-downloader/cnpniohnfphhjihaiiggeabnkjhpaldj)** - 浏览并下载网页上的图像。 28 | * **[Vimium【强烈推荐】](https://chrome.google.com/webstore/detail/vimium/dbepggeogbaibhgnhhndojpepiihcmeb)** - 像 vim 一样操作浏览器。装逼神器。 29 | * **[Context Menu Search](https://chrome.google.com/webstore/detail/context-menu-search/ocpcmghnefmdhljkoiapafejjohldoga)** - 使用右键菜单在不同的搜索引擎中搜索选定的文本。 30 | * **[Google 翻译](https://chrome.google.com/webstore/detail/google-translate/aapbdbdomjkkjkaonfhkkikfgjllcleb)** - 浏览网页时可轻松查看翻译版本。 31 | * **[Octotree【强烈推荐】](https://chrome.google.com/webstore/detail/octotree/bkhaagjahfmjljalopjnoealnfndnagc?hl=en-US)** - 树形结构化显示 GitHub 上的项目代码,更方便查看代码。 32 | * **[GitCodeTree](https://chrome.google.com/webstore/detail/gitcodetree/inaaldjpdbkaodlmdcplgpoibohcmmlj)** - 树形结构化显示码云上的项目代码,更方便查看代码。 33 | * **[The Great Suspender](https://chrome.google.com/webstore/detail/the-great-suspender/klbibkeccnjlkjkiokjodocebajanakg)** - 谷歌浏览器是很耗内存的,该插件会自动挂起长时间未使用的网页,来释放系统资源。 34 | * **[Postman Interceptor【强烈推荐】](https://chrome.google.com/webstore/detail/postman-interceptor/aicmkgpgakddgnaphhhpliifpcfhicfo)** - 大名鼎鼎的 Postman。用来测试接口。 35 | * **[Boomerang - SOAP & REST Client](https://chrome.google.com/webstore/detail/boomerang-soap-rest-clien/eipdnjedkpcnlmmdfdkgfpljanehloah)** - 另一个接口测试插件,无缝集成并测试 SOAP 和 REST 服务。 36 | * **[apizza](https://chrome.google.com/webstore/detail/apizza/kpkajnbnadgmiekpbpjekjmoomkdhiio)** - 体验类似 postman。 37 | * **[SimilarWeb - 网站流量来源和排名【强烈推荐】](https://chrome.google.com/webstore/detail/similarweb-traffic-rank-w/hoklmmgfnpapgjgcpechhaamimifchmp)** - 查看网站参与、流量来源和网站排名信息。 38 | * **[Insight.io for Github](https://chrome.google.com/webstore/detail/insightio-for-github/pmhfgjjhhomfplgmbalncpcohgeijonh)** - 像 IDE 一样智能的查看 GitHub 上项目代码。 39 | * **[Sourcegraph for GitHub【强烈推荐】](https://chrome.google.com/webstore/detail/sourcegraph-for-github/dgjhfomjieaadpoljlnidmbgkdffpack)** - 提供 GitHub IDE 的强大功能:跳转到代码,PR 和差异的定义和悬停工具提示。 40 | * **[Porter Plug](https://chrome.google.com/webstore/detail/porter-plug/lngoojfoglemfpbeiomhgheccpdheilp)** - 使用 Porter.io 的嵌入式回购新闻和图表提升 Github 体验。 41 | * **[Axure RP Extension for Chrome](https://chrome.google.com/webstore/detail/axure-rp-extension-for-ch/dogkpdfcklifaemcdfbildhcofnopogp)** - 可以从 Google Chrome 浏览器本地查看 Axure RP 原型。 42 | * **[Listen 1【强烈推荐】](https://github.com/listen1/listen1_chrome_extension/releases)** - 集成 QQ、网易、虾米三大音乐平台平台听歌插件,程序员专属音乐播放器,良心作品。 43 | * **[Website IP](https://chrome.google.com/webstore/detail/website-ip/ghbmhlgniedlklkpimlibbaoomlpacmk)** - 将当前网站的 IP 显示在右下角,便于本地开发网站调试。 44 | * **[GitHub Hovercard【强烈推荐】](https://chrome.google.com/webstore/detail/github-hovercard/mmoahbbnojgkclgceahhakhnccimnplk)** - 使用这款插件,当你将鼠标停留在 GitHub 网站的用户头像或者仓库链接地址上时,会自动弹出一个悬浮框,带你提前预览基本信息。同性交友利器! 45 | * **[Awesome Autocomplete for GitHub【强烈推荐】](https://chrome.google.com/webstore/detail/awesome-autocomplete-for/djkfdjpoelphhdclfjhnffmnlnoknfnd)** - 将即时搜索功能添加到 GitHub 的搜索栏。 46 | * **[JSON-handle](https://chrome.google.com/webstore/detail/json-handle/iahnhfdhidomcpggpaimmmahffihkfnj)** - JSON 美化插件。 47 | * **[马克飞象【强烈推荐】](https://chrome.google.com/webstore/detail/marxico/kidnkfckhbdkfgbicccmdggmpgogehop?utm_source=chrome-app-launcher-info-dialog)** - 强大的 Markdown 离线编辑器,专为印象笔记打造。 48 | * **[Vysor](https://chrome.google.com/webstore/detail/vysor/gidgenkbbabolejbgbpnhbimgjbffefm?utm_source=chrome-app-launcher-info-dialog)** - 在浏览器上操作 Android 手机。 49 | * **[Draw.io Desktop【强烈推荐】](https://chrome.google.com/webstore/detail/drawio-desktop/pebppomjfocnoigkeepgbmcifnnlndla?utm_source=chrome-app-launcher-info-dialog)** - Draw.io 是一个完全免费的图表编辑器,画流程图特别方便,强烈推荐!!!。 50 | * **[Dark Reader【强烈推荐】](https://chrome.google.com/webstore/detail/dark-reader/eimadpbcbfnmbkopoojfekhnkhdbieeh?utm_source=chrome-ntp-icon)** - 这是一个护眼扩展程序,通过实时生成黑色主题,为每一个网站启用夜间模式。 51 | 52 | ## 油猴脚本 53 | 54 | ### 脚本网站 55 | 56 | * [OpenUserJS](https://openuserjs.org/) - 继 GreasyFork 之后开始创办。它由 Sizzle McTwizzle 创建,同样地,在其储存库中也拥有大量的脚本资源。 57 | * [GreasyFork](https://greasyfork.org/) - 或许是最受欢迎的后起之秀了。它由 Jason Barnabe 创建,Jason Barnabe 同时也是 [Stylish](https://userstyles.org/) 网站的创办者,在其储存库中有大量的脚本资源。 58 | 59 | * Userscripts.org - 一直以来都是用户脚本的常用来源,但现在这个网站已经不再更新了。你可以在这个网址找到历 史资源 [http://userscripts-mirror.org](http://userscripts-mirror.org)。 60 | 61 | * [Sleazy Fork](https://sleazyfork.org/zh-CN/scripts) - 不解释。 62 | 63 | ### 常用脚本 64 | 65 | * **[Userscript+](chrome-extension://dhdgffkkebhmkfjojejmpbldmpobfkfo/ask.html?aid=c27c0624-0639-4f31-ae70-5371b57fba93)** - 显示当前网站所有可用的油猴脚本。 66 | * **[一键离线下载](https://greasyfork.org/zh-CN/scripts/22590-%E4%B8%80%E9%94%AE%E7%A6%BB%E7%BA%BF%E4%B8%8B%E8%BD%BD)** - 一键自动将磁链、bt 种子或其他下载资源离线下载至网盘。 67 | * **[全网音乐一键免费下载 一键搜索 在线试听](https://greasyfork.org/zh-CN/scripts/37058-%E5%85%A8%E7%BD%91%E9%9F%B3%E4%B9%90%E4%B8%80%E9%94%AE%E5%85%8D%E8%B4%B9%E4%B8%8B%E8%BD%BD-%E4%B8%80%E9%94%AE%E6%90%9C%E7%B4%A2-%E5%9C%A8%E7%BA%BF%E8%AF%95%E5%90%AC-%E6%9C%80%E6%96%B0%E4%BF%AE%E5%A4%8D%E7%89%882018-3-10%E6%99%9A%E6%9B%B4%E6%96%B0)** - 全网音乐在线试听 一键免费下载 一键搜索 提供多站合一 音乐试听 音乐下载 音乐搜索解决方案,网易云音乐,QQ 音乐,酷狗音乐,酷我音乐,虾米音乐,百度音乐,蜻蜓 FM,荔枝 FM,喜马拉雅。 68 | * **[JSON formatter](https://greasyfork.org/zh-CN/scripts/10718-json-formatter)** - 美化 JSON 数据。 69 | * **[GitHub Dark Script](https://greasyfork.org/zh-CN/scripts/15562-github-dark-script)** - 设置 GItHub 黑色主题。 70 | * **[破解 VIP 会员视频集合](https://greasyfork.org/zh-CN/scripts/27530-%E7%A0%B4%E8%A7%A3vip%E4%BC%9A%E5%91%98%E8%A7%86%E9%A2%91%E9%9B%86%E5%90%88)** - 一键破解[优酷|腾讯|乐视|爱奇艺|芒果|AB 站|音悦台]等 VIP 或会员视频。 71 | * **[百度搜索 - 优化](https://greasyfork.org/zh-CN/scripts/31642-%E7%99%BE%E5%BA%A6%E6%90%9C%E7%B4%A2-%E4%BC%98%E5%8C%96)** - 1、屏蔽百度推广 2、关闭百度广告联盟信息收集 3、绑定快捷键 4、布局调整 5、居中单列(可选)** 6、居中双列(可选)。 72 | * **[百度网盘直接下载](https://greasyfork.org/zh-CN/scripts/39776-%E7%99%BE%E5%BA%A6%E7%BD%91%E7%9B%98%E9%AB%98%E9%80%9F%E4%B8%8B%E8%BD%BD%E5%8A%A9%E6%89%8B)** - 网盘内和分享链接页面均显示[高速下载]按钮,支持百度企业网盘。 73 | * **[Wikipedia Inline Article Viewer](https://greasyfork.org/zh-CN/scripts/7678-wikipedia-inline-article-viewer)** - 鼠标停在维基百科页面上的链接上,会自动加载连接内容。 74 | * **[跳过网站等待、验证码及登录](https://greasyfork.org/zh-CN/scripts/2600-%E8%B7%B3%E8%BF%87%E7%BD%91%E7%AB%99%E7%AD%89%E5%BE%85-%E9%AA%8C%E8%AF%81%E7%A0%81%E5%8F%8A%E7%99%BB%E5%BD%95)** - 移除各类网站验证码、登录、倒计时及更多! 75 | * **[Google & baidu Switcher (ALL in One)](https://greasyfork.org/zh-CN/scripts/12909-google-baidu-switcher-all-in-one)** - 分别在百度和 google 的搜索结果页面增加搜索跳转按钮。 76 | * **[目录树导航](https://greasyfork.org/zh-CN/scripts/34479-%E7%9B%AE%E5%BD%95%E6%A0%91%E5%AF%BC%E8%88%AA)** - 目录树导航 - 显示文章目录大纲导航 77 | * **[网页限制解除](https://greasyfork.org/zh-CN/scripts/28497-remove-web-limits-modified)** - 通杀大部分网站,可以解除禁止复制、剪切、选择文本、右键菜单的限制。 78 | * **[Wide Github](https://openuserjs.org/scripts/xthexder/Wide_Github)** - 将所有 github 存储库页面更改为全宽显示,[插件版](https://chrome.google.com/webstore/detail/wide-github/kaalofacklcidaampbokdplbklpeldpj)。 79 | * **[GitHub 汉化插件](https://openuserjs.org/scripts/52cik/GitHub_%E6%B1%89%E5%8C%96%E6%8F%92%E4%BB%B6)** - 汉化 GitHub 界面的部分菜单及内容。 80 | -------------------------------------------------------------------------------- /Docs/Images/MVC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanguans/notes/28f78aee232e7430425055b795de2d52242eef27/Docs/Images/MVC.png -------------------------------------------------------------------------------- /Docs/Images/Select-license.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanguans/notes/28f78aee232e7430425055b795de2d52242eef27/Docs/Images/Select-license.jpg -------------------------------------------------------------------------------- /Docs/Images/Vim-molokai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanguans/notes/28f78aee232e7430425055b795de2d52242eef27/Docs/Images/Vim-molokai.png -------------------------------------------------------------------------------- /Docs/Images/man-cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanguans/notes/28f78aee232e7430425055b795de2d52242eef27/Docs/Images/man-cn.png -------------------------------------------------------------------------------- /Docs/Images/the-relationship-between-design-patterns.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanguans/notes/28f78aee232e7430425055b795de2d52242eef27/Docs/Images/the-relationship-between-design-patterns.jpg -------------------------------------------------------------------------------- /Frontend/CSS.md: -------------------------------------------------------------------------------- 1 | # CSS 2 | 3 | 早期的 web 没有样式,只是单纯的文本。通过 CSS,可以实现网页样式和内容的分离。 4 | 5 | 简单来说,CSS 可以指定 HTML 页面上的元素所使用的样式。 6 | 7 | 和其他语言一样,CSS 有很多版本。最新的版本是 CSS 3. CSS 2.0 兼容性最好。 8 | 9 | 你可以使用[dabblet](http://dabblet.com/)来在线测试 CSS 的效果。 10 | 11 | ``` css 12 | /* 注释 */ 13 | 14 | /* #################### 15 | ## 选择器 16 | ####################*/ 17 | 18 | /* 一般而言,CSS的声明语句非常简单。 */ 19 | 选择器 { 属性: 值; /* 更多属性...*/ } 20 | 21 | /* 选择器用于指定页面上的元素。 22 | 23 | 针对页面上的所有元素。 */ 24 | * { color:red; } 25 | 26 | /* 27 | 假定页面上有这样一个元素 28 | 29 |
30 | */ 31 | 32 | /* 你可以通过类名来指定它 */ 33 | .some-class { } 34 | 35 | /* 给出所有类名 */ 36 | .some-class.class2 { } 37 | 38 | /* 标签名 */ 39 | div { } 40 | 41 | /* id */ 42 | #someId { } 43 | 44 | /* 由于元素包含attr属性,因此也可以通过这个来指定 */ 45 | [attr] { font-size:smaller; } 46 | 47 | /* 以及有特定值的属性 */ 48 | [attr='value'] { font-size:smaller; } 49 | 50 | /* 通过属性的值的开头指定 */ 51 | [attr^='val'] { font-size:smaller; } 52 | 53 | /* 通过属性的值的结尾来指定 */ 54 | [attr$='ue'] { font-size:smaller; } 55 | 56 | /* 通过属性的值的部分来指定 */ 57 | [attr~='lu'] { font-size:smaller; } 58 | 59 | 60 | /* 你可以把这些全部结合起来,注意不同部分间不应该有空格,否则会改变语义 */ 61 | div.some-class[attr$='ue'] { } 62 | 63 | /* 你也可以通过父元素来指定。*/ 64 | 65 | /* 某个元素是另一个元素的直接子元素 */ 66 | div.some-parent > .class-name {} 67 | 68 | /* 或者通过该元素的祖先元素 */ 69 | div.some-parent .class-name {} 70 | 71 | /* 注意,去掉空格后语义就不同了。 72 | 你能说出哪里不同么? */ 73 | div.some-parent.class-name {} 74 | 75 | /* 你可以选择某元素前的相邻元素 */ 76 | .i-am-before + .this-element { } 77 | 78 | /* 某元素之前的同级元素(相邻或不相邻) */ 79 | .i-am-any-before ~ .this-element {} 80 | 81 | /* 伪类允许你基于页面的行为指定元素(而不是基于页面结构) */ 82 | 83 | /* 例如,当鼠标悬停在某个元素上时 */ 84 | :hover {} 85 | 86 | /* 已访问过的链接*/ 87 | :visited {} 88 | 89 | /* 未访问过的链接*/ 90 | :link {} 91 | 92 | /* 当前焦点的input元素 */ 93 | :focus {} 94 | 95 | 96 | /* #################### 97 | ## 属性 98 | ####################*/ 99 | 100 | 选择器 { 101 | 102 | /* 单位 */ 103 | width: 50%; /* 百分比 */ 104 | font-size: 2em; /* 当前字体大小的两倍 */ 105 | width: 200px; /* 像素 */ 106 | font-size: 20pt; /* 点 */ 107 | width: 5cm; /* 厘米 */ 108 | width: 50mm; /* 毫米 */ 109 | width: 5in; /* 英尺 */ 110 | 111 | /* 颜色 */ 112 | background-color: #F6E; /* 短16位 */ 113 | background-color: #F262E2; /* 长16位 */ 114 | background-color: tomato; /* 颜色名称 */ 115 | background-color: rgb(255, 255, 255); /* rgb */ 116 | background-color: rgb(10%, 20%, 50%); /* rgb 百分比 */ 117 | background-color: rgba(255, 0, 0, 0.3); /* rgb 加透明度 */ 118 | 119 | /* 图片 */ 120 | background-image: url(/path-to-image/image.jpg); 121 | 122 | /* 字体 */ 123 | font-family: Arial; 124 | font-family: "Courier New"; /* 使用双引号包裹含空格的字体名称 */ 125 | font-family: "Courier New", Trebuchet, Arial; /* 如果第一个 126 | 字体没找到,浏览器会使用第二个字体,一次类推 */ 127 | } 128 | 129 | ``` 130 | 131 | ## 使用 132 | 133 | CSS 文件使用 `.css` 后缀。 134 | 135 | ```xml 136 | 137 | 138 | 139 | 140 | 143 | 144 | 146 |
147 |
148 | 149 | ``` 150 | 151 | ## 优先级 152 | 153 | 同一个元素可能被多个不同的选择器指定,因此可能会有冲突。 154 | 155 | 假定 CSS 是这样的: 156 | 157 | ```css 158 | /*A*/ 159 | p.class1[attr='value'] 160 | 161 | /*B*/ 162 | p.class1 {} 163 | 164 | /*C*/ 165 | p.class2 {} 166 | 167 | /*D*/ 168 | p {} 169 | 170 | /*E*/ 171 | p { property: value !important; } 172 | 173 | ``` 174 | 175 | 然后标记语言为: 176 | 177 | ```xml 178 |

179 |

180 | ``` 181 | 182 | 那么将会按照下面的顺序应用风格: 183 | 184 | 185 | * `E` 优先级最高,因为它使用了 `!important`,除非很有必要,尽量避免使用这个。 186 | * `F` 其次,因为它是嵌入的风格。 187 | * `A` 其次,因为它比其他指令更具体。 188 | * `C` 其次,虽然它的具体程度和`B`一样,但是它在`B`之后。 189 | * 接下来是 `B`。 190 | * 最后是 `D`。 191 | 192 | ## 兼容性 193 | 194 | CSS2 的绝大部分特性兼容各种浏览器和设备。现在 CSS3 的兼容性也越来越好了。 195 | 但是兼容性问题仍然是需要留意的一个问题。 196 | 197 | [QuirksMode CSS](http://www.quirksmode.org/css/)是关于这方面最好的资源。 198 | 199 | ## 扩展阅读 200 | 201 | * [理解 CSS 的风格优先级: 特定性, 继承和层叠](http://www.vanseodesign.com/css/css-specificity-inheritance-cascaade/) 202 | * [QuirksMode CSS](http://www.quirksmode.org/css/) 203 | * [Z-Index - The stacking context](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context) 204 | -------------------------------------------------------------------------------- /Frontend/HTML.md: -------------------------------------------------------------------------------- 1 | # HTML 2 | 3 | HTML 是超文本标记语言的缩写。 4 | 这门语言可以让我们为万维网创造页面。 5 | 这是一门标记语言,它允许我们用代码来指示网页上文字和数据应该如何显示。 6 | 实际上 html 文件是简单的文本文件。 7 | 什么是标记?标记是通过使用开始和结束标签包围数据的方法,来组织管理页面上的数据。 8 | 这些标记对它们环绕的文本有重要的意义。 9 | 和其它计算机语言意义,HTML 有很多版本。这里我们将讨论 HTML5。 10 | 11 | **注意:** 你可以在类似[codepen](http://codepen.io/pen/)的网站上的教程中,尝试不同的标签和元素带来的效果,理解它们如何起效,并且逐渐熟悉这门语言。 12 | 本文主要关注 HTML 的语法和一些有用的小窍门。 13 | 14 | ```html 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 我的网站 25 | 26 | 27 |

Hello, world!

28 | 来看看这里有什么 29 |

这是一个段落。

30 |

这是另外一个段落。

31 |
    32 |
  • 这是一个非计数列表的一项(项目符合列表)
  • 33 |
  • 这是另一项
  • 34 |
  • 这是列表中的最后一项
  • 35 |
36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 我的网站 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 |

Hello, world!

65 | 66 | 来看看这里有什么 67 |

这是一个段落。

68 |

这是另外一个段落。

69 |
    70 | 71 |
  • 这是一个非计数列表的一项(项目符合列表)
  • 72 |
  • 这是另一项
  • 73 |
  • 这是列表中的最后一项
  • 74 |
75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 |
第一个表头 第二个表头
第一行第一列 第一行第二列
第二行第一列第二行第二列
101 | 102 | ``` 103 | 104 | ## 使用 105 | 106 | HTML 文件使用`.html`后缀。 107 | 108 | ## 扩展阅读 109 | 110 | * [维基百科](https://en.wikipedia.org/wiki/HTML) 111 | * [HTML tutorial](https://developer.mozilla.org/en-US/docs/Web/HTML) 112 | * [W3School](http://www.w3schools.com/html/html_intro.asp) 113 | -------------------------------------------------------------------------------- /Frontend/JSON.md: -------------------------------------------------------------------------------- 1 | # JSON 2 | 3 | 因为 JSON 是一个极其简单的数据交换格式,本教程最有可能成为有史以来最简单的 4 | Learn X in Y Minutes。 5 | 6 | 纯正的 JSON 实际上没有注释,但是大多数解析器都 7 | 接受 C-风格(//, /\* \*/)的注释。为了兼容性,最好不要在其中写这样形式的注释。 8 | 9 | 因此,本教程的一切都会是 100%有效的 JSON。幸亏,它的表达能力很丰富。 10 | 11 | 支持的数据类型: 12 | 13 | - 字符串: "hello", "\"A quote.\"", "\u0abe", "Newline.\n" 14 | - 数字: 23, 0.11, 12e10, 3.141e-10, 1.23e+4 15 | - 对象: { "key": "value" } 16 | - 数组: ["Values"] 17 | - 其他: true, false, null 18 | 19 | ```json 20 | { 21 | "numbers": 0, 22 | "strings": "Hellø, wørld. All unicode is allowed, along with \"escaping\".", 23 | "has bools?": true, 24 | "nothingness": null, 25 | 26 | "big number": 1.2e+100, 27 | 28 | "objects": { 29 | "comment": "Most of your structure will come from objects.", 30 | 31 | "array": [0, 1, 2, 3, "Arrays can have anything in them.", 5], 32 | 33 | "another object": { 34 | "comment": "These things can be nested, very useful." 35 | } 36 | }, 37 | 38 | "silliness": [ 39 | { 40 | "sources of potassium": ["bananas"] 41 | }, 42 | [ 43 | [1, 0, 0, 0], 44 | [0, 1, 0, 0], 45 | [0, 0, 1, "neo"], 46 | [0, 0, 0, 1] 47 | ] 48 | ], 49 | 50 | "that was short": "And, you're done. You now know everything JSON has to offer." 51 | } 52 | ``` 53 | -------------------------------------------------------------------------------- /Frontend/Less.md: -------------------------------------------------------------------------------- 1 | # Less 2 | 3 | Less 是一种 CSS 预处理器,它增加了诸如变量、嵌套、mixin 等功能。 4 | Less(以及其它预处理器,如[Sass](http://sass-lang.com/))能帮助开发人员编写易维护,DRY (Don't Repeat Yourself) 的代码。 5 | 6 | ```css 7 | 8 | 9 | //单行注释在编译成CSS后会被删除。 10 | 11 | /* 多行注释将保留. */ 12 | 13 | 14 | 15 | /* 变量 16 | ==============================*/ 17 | 18 | 19 | /* 你可以将一个CSS值(如一个颜色值)保存到变量中。 20 | 使用'@'符号来创建一个变量。*/ 21 | 22 | @primary-color: #a3a4ff; 23 | @secondary-color: #51527f; 24 | @body-font: 'Roboto', sans-serif; 25 | 26 | /* 你可以在你的样式文件中使用这些变量。 27 | 现在假如你想修改颜色,你只需修改一次即可。*/ 28 | 29 | body { 30 | background-color: @primary-color; 31 | color: @secondary-color; 32 | font-family: @body-font; 33 | } 34 | 35 | /* 以上将编译成: */ 36 | 37 | body { 38 | background-color: #a3a4ff; 39 | color: #51527F; 40 | font-family: 'Roboto', sans-serif; 41 | } 42 | 43 | 44 | /* 相比于在你的样式文件中逐个修改,这种方式维护性更好。 */ 45 | 46 | 47 | 48 | /* Mixins 49 | ==============================*/ 50 | 51 | 52 | /* 如果你要为多个元素编写同样的代码, 53 | 你可能想实现轻松地重用。*/ 54 | 55 | .center { 56 | display: block; 57 | margin-left: auto; 58 | margin-right: auto; 59 | left: 0; 60 | right: 0; 61 | } 62 | 63 | /* 你只需简单地将选择子作为样式添加进来就能使用mixin了 */ 64 | 65 | div { 66 | .center; 67 | background-color: @primary-color; 68 | } 69 | 70 | /* 它将编译成: */ 71 | 72 | .center { 73 | display: block; 74 | margin-left: auto; 75 | margin-right: auto; 76 | left: 0; 77 | right: 0; 78 | } 79 | div { 80 | display: block; 81 | margin-left: auto; 82 | margin-right: auto; 83 | left: 0; 84 | right: 0; 85 | background-color: #a3a4ff; 86 | } 87 | 88 | /* 通过在选择子后添加括号,可以使这些mixin代码不被编译 */ 89 | 90 | .center() { 91 | display: block; 92 | margin-left: auto; 93 | margin-right: auto; 94 | left: 0; 95 | right: 0; 96 | } 97 | 98 | div { 99 | .center; 100 | background-color: @primary-color; 101 | } 102 | 103 | /* 将编译成: */ 104 | div { 105 | display: block; 106 | margin-left: auto; 107 | margin-right: auto; 108 | left: 0; 109 | right: 0; 110 | background-color: #a3a4ff; 111 | } 112 | 113 | 114 | 115 | /* 嵌套 116 | ==============================*/ 117 | 118 | 119 | /* Less允许你在选择子中嵌套选择子 */ 120 | 121 | ul { 122 | list-style-type: none; 123 | margin-top: 2em; 124 | 125 | li { 126 | background-color: #f00; 127 | } 128 | } 129 | 130 | /* '&'将被替换成父选择子。*/ 131 | /* 你也可以嵌套伪类。 */ 132 | /* 注意过度嵌套将会导致代码难以维护。 133 | 最佳实践推荐在嵌套时不超过3层。 134 | 例如: */ 135 | 136 | ul { 137 | list-style-type: none; 138 | margin-top: 2em; 139 | 140 | li { 141 | background-color: red; 142 | 143 | &:hover { 144 | background-color: blue; 145 | } 146 | 147 | a { 148 | color: white; 149 | } 150 | } 151 | } 152 | 153 | /* 编译成: */ 154 | 155 | ul { 156 | list-style-type: none; 157 | margin-top: 2em; 158 | } 159 | 160 | ul li { 161 | background-color: red; 162 | } 163 | 164 | ul li:hover { 165 | background-color: blue; 166 | } 167 | 168 | ul li a { 169 | color: white; 170 | } 171 | 172 | 173 | 174 | /* 函数 175 | ==============================*/ 176 | 177 | 178 | /* Less提供的函数可以用来完成多种任务。 179 | 考虑以下情况: */ 180 | 181 | /* 函数可以通过其名称及传入其所需的参数来调用。 */ 182 | 183 | body { 184 | width: round(10.25px); 185 | } 186 | 187 | .header { 188 | background-color: lighten(#000, 0.5); 189 | } 190 | 191 | .footer { 192 | background-color: fadeout(#000, 0.25) 193 | } 194 | 195 | /* 编译成: */ 196 | 197 | body { 198 | width: 10px; 199 | } 200 | 201 | .header { 202 | background-color: #010101; 203 | } 204 | 205 | .footer { 206 | background-color: rgba(0, 0, 0, 0.75); 207 | } 208 | 209 | /* 你也可以定义自己的函数。函数非常类似于mixin。 210 | 当你在函数和mixin之间抉择时, 211 | 记住mixin最适合用来创建CSS而函数更适合于 212 | 处理那些可能在你的Less代码中使用的逻辑。 213 | '数学运算符'部分的例子是转成可重用函数的最佳选择。*/ 214 | 215 | /* 该函数计算两数的平均值: */ 216 | 217 | .average(@x, @y) { 218 | @average-result: ((@x + @y) / 2); 219 | } 220 | 221 | div { 222 | .average(16px, 50px); // "调用"mixin 223 | padding: @average-result; // 使用它的"返回"值 224 | } 225 | 226 | /* 编译成: */ 227 | 228 | div { 229 | padding: 33px; 230 | } 231 | 232 | 233 | 234 | /* 扩展 (继承) 235 | ==============================*/ 236 | 237 | 238 | /* 扩展是在选择子间共享属性的一种方法。 */ 239 | 240 | .display { 241 | height: 50px; 242 | } 243 | 244 | .display-success { 245 | &:extend(.display); 246 | border-color: #22df56; 247 | } 248 | 249 | /* 编译成: */ 250 | .display, 251 | .display-success { 252 | height: 50px; 253 | } 254 | .display-success { 255 | border-color: #22df56; 256 | } 257 | 258 | /* 扩展一条CSS语句优于创建一个mixin, 259 | 这是由其组合所有共享相同基样式的类的方式决定的。 260 | 如果使用mixin完成,其属性将会在调用了该mixin的每条语句中重复。 261 | 虽然它不至会影响你的工作流,但它会在由Less编译器 262 | 生成的的文件中添加不必要的代码。*/ 263 | 264 | 265 | 266 | /* 片段与导入 267 | ==============================*/ 268 | 269 | 270 | /* Less允许你创建片段文件。它有助于你的Less代码保持模块化。 271 | 片段文件习惯上以'_'开头,例如 _reset.css,并被导入到 272 | 一个将会被编译成CSS的主less文件中。*/ 273 | 274 | /* 考虑以下的CSS,我们将把它们放入一个叫_reset.css的文件中 */ 275 | 276 | html, 277 | body, 278 | ul, 279 | ol { 280 | margin: 0; 281 | padding: 0; 282 | } 283 | 284 | /* Less提供的@import能用来将片段导入到文件中。 285 | 它与传统的CSS @import语句不同,无需通过 286 | HTTP请求获取导入文件。Less提取导入文件 287 | 并将它们与编译后的代码结合起来。 */ 288 | 289 | @import 'reset'; 290 | 291 | body { 292 | font-size: 16px; 293 | font-family: Helvetica, Arial, Sans-serif; 294 | } 295 | 296 | /* 编译成: */ 297 | 298 | html, body, ul, ol { 299 | margin: 0; 300 | padding: 0; 301 | } 302 | 303 | body { 304 | font-size: 16px; 305 | font-family: Helvetica, Arial, Sans-serif; 306 | } 307 | 308 | 309 | 310 | /* 数学运算符 311 | ==============================*/ 312 | 313 | 314 | /* Less提供以下的运算符: +, -, *, /, 和 %。 315 | 相比于使用你事先手工计算好了的数值,它们 316 | 对于直接在你的Less文件中计算数值很有用。 317 | 以下是设置一个两列设计的例子。*/ 318 | 319 | @content-area: 960px; 320 | @main-content: 600px; 321 | @sidebar-content: 300px; 322 | 323 | @main-size: @main-content / @content-area * 100%; 324 | @sidebar-size: @sidebar-content / @content-area * 100%; 325 | @gutter: 100% - (@main-size + @sidebar-size); 326 | 327 | body { 328 | width: 100%; 329 | } 330 | 331 | .main-content { 332 | width: @main-size; 333 | } 334 | 335 | .sidebar { 336 | width: @sidebar-size; 337 | } 338 | 339 | .gutter { 340 | width: @gutter; 341 | } 342 | 343 | /* 编译成: */ 344 | 345 | body { 346 | width: 100%; 347 | } 348 | 349 | .main-content { 350 | width: 62.5%; 351 | } 352 | 353 | .sidebar { 354 | width: 31.25%; 355 | } 356 | 357 | .gutter { 358 | width: 6.25%; 359 | } 360 | 361 | 362 | ``` 363 | 364 | ## 实践 Less 365 | 366 | 如果你想在你的浏览器中尝试 LESS,参阅: 367 | * [Codepen](http://codepen.io/) 368 | * [LESS2CSS](http://lesscss.org/less-preview/) 369 | 370 | ## 兼容性 371 | 372 | Less 可以用于任何项目中,只要你有程序能将它编译成 CSS 即可。你还需要验证你所使用的 CSS 是否与你的目标浏览器兼容。 373 | 374 | [QuirksMode CSS](http://www.quirksmode.org/css/)和[CanIUse](http://caniuse.com) 对于检查兼容性来说都是不错的资源。 375 | 376 | ## 延伸阅读资料 377 | * [Official Documentation](http://lesscss.org/features/) 378 | * [Less CSS - Beginner's Guide](http://www.hongkiat.com/blog/less-basic/) 379 | -------------------------------------------------------------------------------- /Frontend/Sass.md: -------------------------------------------------------------------------------- 1 | # Sass 2 | 3 | Sass 是一种 CSS 扩展语言,它增加了诸如变量、嵌套、mixin 等功能。 4 | Sass(以及其它预处理器,如[Less](http://lesscss.org/)等) 能帮助开发人员编写易维护和 DRY (Don't Repeat Yourself)的代码。 5 | 6 | Sass 有两种不同的语法可选用。SCSS 的语法和 CSS 的相同,但增加了 Sass 的额外功能。或者 Sass(原来的语法),它使用缩进而非大括号和分号。 7 | 8 | 本教程使用 SCSS 编写。 9 | 10 | 如果你已熟悉 CSS3,你可能相对能较快地掌握 Sass。它并没有提供任何新的类型属性,而只是提供了一些工具使你能更高效的编写 CSS,并且使维护更加容易。 11 | 12 | ```scss 13 | 14 | 15 | // 单行注释当Sass被编译成CSS后会被删除。 16 | 17 | /* 多行注释将保留. */ 18 | 19 | /* 变量 20 | ============================== */ 21 | 22 | 23 | 24 | /* 你可以将一个CSS值(如一个颜色值)保存到变量中。 25 | 使用'$'符号来创建一个变量。*/ 26 | 27 | $primary-color: #A3A4FF; 28 | $secondary-color: #51527F; 29 | $body-font: 'Roboto', sans-serif; 30 | 31 | /* 你可以在你的样式文件中使用变量。 32 | 现在假如你想修改颜色,你只需修改一次即可。*/ 33 | 34 | body { 35 | background-color: $primary-color; 36 | color: $secondary-color; 37 | font-family: $body-font; 38 | } 39 | 40 | /* 以上将编译成: */ 41 | body { 42 | background-color: #A3A4FF; 43 | color: #51527F; 44 | font-family: 'Roboto', sans-serif; 45 | } 46 | 47 | /* 相比于在你的样式文件中逐个进行修改,这种方式维护性更好。 */ 48 | 49 | 50 | 51 | /* 控制指令 52 | ============================== */ 53 | 54 | /* Sass允许你使用@if, @else, @for, @while, 和 @each 来控制 55 | 你的代码如何编译成CSS */ 56 | 57 | /* @if/@else块的行为和你可能预想的会完全相同 */ 58 | 59 | $debug: true !default; 60 | 61 | @mixin debugmode { 62 | @if $debug { 63 | @debug "Debug mode enabled"; 64 | 65 | display: inline-block; 66 | } 67 | @else { 68 | display: none; 69 | } 70 | } 71 | 72 | .info { 73 | @include debugmode; 74 | } 75 | 76 | /* 如果$debug设置为了true, .info 将会显示; 如果设置为false那么 77 | .info 将不显示。 78 | 79 | 注意: @debug将在命令行中输出调试信息。 80 | 在调试你的SCSS时它对于检查变量很有用。*/ 81 | 82 | .info { 83 | display: inline-block; 84 | } 85 | 86 | /* @for是控制循环,它能遍历区间值。 87 | 它对于设置一组元素的类型特别有用。 88 | 有两种形式,"through"和"to"。前者包括最末那个值, 89 | 而后者止于最末那个值。 90 | */ 91 | 92 | @for $c from 1 to 4 { 93 | div:nth-of-type(#{$c}) { 94 | left: ($c - 1) * 900 / 3; 95 | } 96 | } 97 | 98 | @for $c from 1 through 3 { 99 | .myclass-#{$c} { 100 | color: rgb($c * 255 / 3, $c * 255 / 3, $c * 255 / 3); 101 | } 102 | } 103 | 104 | /* 将编译成: */ 105 | 106 | div:nth-of-type(1) { 107 | left: 0; 108 | } 109 | 110 | div:nth-of-type(2) { 111 | left: 300; 112 | } 113 | 114 | div:nth-of-type(3) { 115 | left: 600; 116 | } 117 | 118 | .myclass-1 { 119 | color: #555555; 120 | } 121 | 122 | .myclass-2 { 123 | color: #aaaaaa; 124 | } 125 | 126 | .myclass-3 { 127 | color: white; 128 | // SASS automatically converts #FFFFFF to white 129 | } 130 | 131 | /* @while也非常直白: */ 132 | 133 | $columns: 4; 134 | $column-width: 80px; 135 | 136 | @while $columns > 0 { 137 | .col-#{$columns} { 138 | width: $column-width; 139 | left: $column-width * ($columns - 1); 140 | } 141 | 142 | $columns: $columns - 1; 143 | } 144 | 145 | /* 将输出以下CSS: */ 146 | 147 | .col-4 { 148 | width: 80px; 149 | left: 240px; 150 | } 151 | 152 | .col-3 { 153 | width: 80px; 154 | left: 160px; 155 | } 156 | 157 | .col-2 { 158 | width: 80px; 159 | left: 80px; 160 | } 161 | 162 | .col-1 { 163 | width: 80px; 164 | left: 0px; 165 | } 166 | 167 | /* @each函数类似@for, 除了它使用一个列表而不是序列值 168 | 注意: 你指定列表的方式和指定其它变量一样, 169 | 用空格作为分隔符。 */ 170 | 171 | $social-links: facebook twitter linkedin reddit; 172 | 173 | .social-links { 174 | @each $sm in $social-links { 175 | .icon-#{$sm} { 176 | background-image: url("images/#{$sm}.png"); 177 | } 178 | } 179 | } 180 | 181 | /* 将输出: */ 182 | 183 | .social-links .icon-facebook { 184 | background-image: url("images/facebook.png"); 185 | } 186 | 187 | .social-links .icon-twitter { 188 | background-image: url("images/twitter.png"); 189 | } 190 | 191 | .social-links .icon-linkedin { 192 | background-image: url("images/linkedin.png"); 193 | } 194 | 195 | .social-links .icon-reddit { 196 | background-image: url("images/reddit.png"); 197 | } 198 | 199 | 200 | /* Mixins 201 | ==============================*/ 202 | 203 | /* 如果你发现你要为多个元素编写相同的代码, 204 | 你可能想将那些代码保存到一个mixin中。 205 | 206 | 使用'@mixin'指令,再为你的mixin加上一个名称。*/ 207 | 208 | @mixin center { 209 | display: block; 210 | margin-left: auto; 211 | margin-right: auto; 212 | left: 0; 213 | right: 0; 214 | } 215 | 216 | /* 你可以通过'@include'及mixin名来调用mixin。 */ 217 | 218 | div { 219 | @include center; 220 | background-color: $primary-color; 221 | } 222 | 223 | /* 将编译成: */ 224 | div { 225 | display: block; 226 | margin-left: auto; 227 | margin-right: auto; 228 | left: 0; 229 | right: 0; 230 | background-color: #A3A4FF; 231 | } 232 | 233 | /* 你可以使用mixin来创建一个快捷属性。*/ 234 | 235 | @mixin size($width, $height) { 236 | width: $width; 237 | height: $height; 238 | } 239 | 240 | /* 你可以通过传入width和height参数来调用它。*/ 241 | 242 | .rectangle { 243 | @include size(100px, 60px); 244 | } 245 | 246 | .square { 247 | @include size(40px, 40px); 248 | } 249 | 250 | /* 编译成: */ 251 | .rectangle { 252 | width: 100px; 253 | height: 60px; 254 | } 255 | 256 | .square { 257 | width: 40px; 258 | height: 40px; 259 | } 260 | 261 | 262 | 263 | /* 函数 264 | ============================== */ 265 | 266 | 267 | 268 | /* Sass提供的函数可以用来完成各种各样的任务。 269 | 考虑以下情况 */ 270 | 271 | /* 函数可以通过其名称及传入其所需的参数来调用 */ 272 | body { 273 | width: round(10.25px); 274 | } 275 | 276 | .footer { 277 | background-color: fade_out(#000000, 0.25); 278 | } 279 | 280 | /* 编译成: */ 281 | 282 | body { 283 | width: 10px; 284 | } 285 | 286 | .footer { 287 | background-color: rgba(0, 0, 0, 0.75); 288 | } 289 | 290 | /* 你也可以定义你自己的函数。函数非常类似于mixin。 291 | 当你在函数和mixin之间抉择时,记住mixin最适合于创建CSS而函数更适合于 292 | 处理那些可能在你的Sass代码中使用的逻辑。'数学运算符'部分的例子 293 | 是转成可重用函数的最理想选择。 */ 294 | 295 | /* 该函数将接收一个目标尺寸大小和父结点尺寸大小,然后计算并 296 | 返回百分数 */ 297 | 298 | @function calculate-percentage($target-size, $parent-size) { 299 | @return $target-size / $parent-size * 100%; 300 | } 301 | 302 | $main-content: calculate-percentage(600px, 960px); 303 | 304 | .main-content { 305 | width: $main-content; 306 | } 307 | 308 | .sidebar { 309 | width: calculate-percentage(300px, 960px); 310 | } 311 | 312 | /* 编译成: */ 313 | 314 | .main-content { 315 | width: 62.5%; 316 | } 317 | 318 | .sidebar { 319 | width: 31.25%; 320 | } 321 | 322 | 323 | 324 | /* 扩展 (继承) 325 | ============================== */ 326 | 327 | 328 | 329 | /* 扩展是在选择子间共享属性的一种方法。 */ 330 | 331 | .display { 332 | @include size(5em, 5em); 333 | border: 5px solid $secondary-color; 334 | } 335 | 336 | .display-success { 337 | @extend .display; 338 | border-color: #22df56; 339 | } 340 | 341 | /* 编译成: */ 342 | .display, .display-success { 343 | width: 5em; 344 | height: 5em; 345 | border: 5px solid #51527F; 346 | } 347 | 348 | .display-success { 349 | border-color: #22df56; 350 | } 351 | 352 | /* 扩展一条CSS语句优于创建一个mixin, 353 | 这是由Sass组合所有共享相同基样式的类的方式决定的。 354 | 如果使用mixin完成,width, height, 和border将会在 355 | 调用了该mixin的每条语句中重复。虽然它不至于会影响你的工作流, 356 | 但它会在由Sass编译器生成的的文件中添加不必要的代码。*/ 357 | 358 | 359 | /* 嵌套 360 | ============================== */ 361 | 362 | 363 | 364 | /* Sass允许在选择子中嵌套选择子 */ 365 | 366 | ul { 367 | list-style-type: none; 368 | margin-top: 2em; 369 | 370 | li { 371 | background-color: #FF0000; 372 | } 373 | } 374 | 375 | /* '&'将被父选择子替换。*/ 376 | /* 你也可以嵌套伪类。 */ 377 | /* 注意过度嵌套将导致你的代码难以维护。 378 | 最佳实践推荐在嵌套时不超过3层。 379 | 例如: */ 380 | 381 | ul { 382 | list-style-type: none; 383 | margin-top: 2em; 384 | 385 | li { 386 | background-color: red; 387 | 388 | &:hover { 389 | background-color: blue; 390 | } 391 | 392 | a { 393 | color: white; 394 | } 395 | } 396 | } 397 | 398 | /* 编译成: */ 399 | 400 | ul { 401 | list-style-type: none; 402 | margin-top: 2em; 403 | } 404 | 405 | ul li { 406 | background-color: red; 407 | } 408 | 409 | ul li:hover { 410 | background-color: blue; 411 | } 412 | 413 | ul li a { 414 | color: white; 415 | } 416 | 417 | 418 | 419 | /* 片段与导入 420 | ============================== */ 421 | 422 | 423 | 424 | /* Sass允许你创建片段文件。它有助于你的Sass代码保持模块化。 425 | 片段文件应该以 '_' 开头,例如 _reset.css。 426 | 片段不会输出到CSS中。*/ 427 | 428 | /* 考虑以下的CSS,我们会将它们放入一个叫作_reset.css的文件中 */ 429 | 430 | html, 431 | body, 432 | ul, 433 | ol { 434 | margin: 0; 435 | padding: 0; 436 | } 437 | 438 | /* Sass提供的@import能用来将片段导入到文件中。 439 | 它与传统的CSS @import语句不同,不需要通过 440 | 另外的HTTP请求来获取导入的文件。 441 | Sass提取导入文件并将它与编译后的代码结合起来。 */ 442 | 443 | @import 'reset'; 444 | 445 | body { 446 | font-size: 16px; 447 | font-family: Helvetica, Arial, Sans-serif; 448 | } 449 | 450 | /* 编译成: */ 451 | 452 | html, body, ul, ol { 453 | margin: 0; 454 | padding: 0; 455 | } 456 | 457 | body { 458 | font-size: 16px; 459 | font-family: Helvetica, Arial, Sans-serif; 460 | } 461 | 462 | 463 | 464 | /* 占位符选择子 465 | ============================== */ 466 | 467 | 468 | 469 | /* 占位符在创建用于扩展的CSS语句时非常有用。 470 | 如果你想创建一条只通过@extend使用的CSS语句,你可以利用占位符来实现。 471 | 占位符以'%'而非'.'或'#'开头。占位符不会出现在编译后的CSS中 */ 472 | 473 | %content-window { 474 | font-size: 14px; 475 | padding: 10px; 476 | color: #000; 477 | border-radius: 4px; 478 | } 479 | 480 | .message-window { 481 | @extend %content-window; 482 | background-color: #0000ff; 483 | } 484 | 485 | /* 编译成: */ 486 | 487 | .message-window { 488 | font-size: 14px; 489 | padding: 10px; 490 | color: #000; 491 | border-radius: 4px; 492 | } 493 | 494 | .message-window { 495 | background-color: #0000ff; 496 | } 497 | 498 | 499 | 500 | /* 数学运算 501 | ============================== */ 502 | 503 | 504 | 505 | /* Sass提供以下的运算符: +, -, *, /, 和 %。它们 506 | 相比于使用你事先手工计算好了的数值,它们 507 | 对于直接在你的Sass文件中计算数值很有用。 508 | 以下是设置一个简单的两列设计的例子。*/ 509 | 510 | $content-area: 960px; 511 | $main-content: 600px; 512 | $sidebar-content: 300px; 513 | 514 | $main-size: $main-content / $content-area * 100%; 515 | $sidebar-size: $sidebar-content / $content-area * 100%; 516 | $gutter: 100% - ($main-size + $sidebar-size); 517 | 518 | body { 519 | width: 100%; 520 | } 521 | 522 | .main-content { 523 | width: $main-size; 524 | } 525 | 526 | .sidebar { 527 | width: $sidebar-size; 528 | } 529 | 530 | .gutter { 531 | width: $gutter; 532 | } 533 | 534 | /* 编译成: */ 535 | 536 | body { 537 | width: 100%; 538 | } 539 | 540 | .main-content { 541 | width: 62.5%; 542 | } 543 | 544 | .sidebar { 545 | width: 31.25%; 546 | } 547 | 548 | .gutter { 549 | width: 6.25%; 550 | } 551 | 552 | ``` 553 | 554 | ## SASS 还是 Sass 555 | 该语言的名字,“Sass”,是一个词,不是一个缩写。 556 | 你有没想过 Sass 是否是一个缩写词?你可能没有,但我反正会告诉你。 557 | 该语言的名字是一个单词,不是一个缩写词。 558 | 由于人们老是将它写成"SASS",语言的作者开玩笑地称它为"Syntactically Awesome StyleSheets"。 559 | 560 | 561 | ## 实践 Sass 562 | 如果你想在你的浏览器中尝试 Sass,参阅[SassMeister](http://sassmeister.com/)。 563 | 你可以选用任一种语法,只需进到设置页然后选择 Sass 或 SCSS。 564 | 565 | 566 | ## 兼容性 567 | Sass 可以用于任何项目中,只要你有程序能将它编译成 CSS 即可。你还需要验证你所使用的 CSS 是否与你的目标浏览器兼容。 568 | 569 | [QuirksMode CSS](http://www.quirksmode.org/css/)和[CanIUse](http://caniuse.com)对于检查兼容性来说都是不错的资源。 570 | 571 | 572 | ## 延伸阅读资料 573 | * [Official Documentation](http://sass-lang.com/documentation/file.SASS_REFERENCE.html) 574 | * [The Sass Way](http://thesassway.com/) 上提供了教程(初学者-高级)和文章。 575 | -------------------------------------------------------------------------------- /Frontend/XML.md: -------------------------------------------------------------------------------- 1 | # XML 2 | 3 | XML 是一种标记语言,被设计用来存储数据和传输数据。 4 | 5 | 不像 HTML, XML 不指定怎样显示或格式化数据,只是携带它。 6 | 7 | * XML 语法 8 | 9 | ```xml 10 | 11 | 12 | 13 | 14 | 15 | Everyday Italian 16 | Giada De Laurentiis 17 | 2005 18 | 30.00 19 | 20 | 21 | Harry Potter 22 | J K. Rowling 23 | 2005 24 | 29.99 25 | 26 | 27 | Learning XML 28 | Erik T. Ray 29 | 2003 30 | 39.95 31 | 32 | 33 | 34 | 41 | 42 | 43 | 44 | 51 | 52 | 53 | 54 | computer.gif 55 | 56 | 57 | ``` 58 | 59 | * 良好格式的文件 x 验证 60 | 61 | 一个 XML 文件是良好格式的如果它是语法正确的。 62 | 但是, 使用文件定义,比如 DTD 和 XML 概要,在文件中插入更多的限制是可能的。 63 | 64 | 一个遵守一个文件定义的 XML 文件被叫做有效的,对于那个文件来说。 65 | 66 | 有了这个工具,你能够在应用逻辑之外检查 XML 数据。 67 | 68 | ```xml 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | Everyday Italian 77 | 30.00 78 | 79 | 80 | 81 | 82 | 83 | 86 | 87 | 88 | 89 | 90 | ]> 91 | 92 | 93 | 98 | 99 | 100 | 101 | 102 | 103 | 106 | 107 | 108 | 109 | 110 | ]> 111 | 112 | 113 | 114 | Everyday Italian 115 | 30.00 116 | 117 | 118 | ``` 119 | -------------------------------------------------------------------------------- /Frontend/YAML.md: -------------------------------------------------------------------------------- 1 | # YAML 2 | 3 | YAML 是一个数据序列化语言,被设计成人类直接可写可读的。 4 | 5 | 它是 JSON 的严格超集,增加了语法显著换行符和缩进,就像 Python。但和 Python 不一样, 6 | YAML 根本不容许文字制表符。 7 | 8 | ```yaml 9 | # YAML 中的注解看起来像这样。 10 | 11 | ################ 12 | # 标量类型 # 13 | ################ 14 | 15 | # 我们的根对象 (它们在整个文件里延续) 将会是一个映射, 16 | # 它等价于在别的语言里的一个字典,哈西表或对象。 17 | key: value 18 | another_key: Another value goes here. 19 | a_number_value: 100 20 | # 如果你想将数字 1 作为值,你必须要将它括在引号中。 21 | # 不然 YAML 解析器会假定它是一个布尔值 true。 22 | scientific_notation: 1e+12 23 | boolean: true 24 | null_value: null 25 | key with spaces: value 26 | # 注意到字符串不需要被括在引号中。但是,它们可以被括起来。 27 | "Keys can be quoted too.": "Useful if you want to put a ':' in your key." 28 | 29 | # 多行字符串既可以写成像一个'文字块'(使用 |), 30 | # 或像一个'折叠块'(使用 '>')。 31 | literal_block: | 32 | This entire block of text will be the value of the 'literal_block' key, 33 | with line breaks being preserved. 34 | 35 | The literal continues until de-dented, and the leading indentation is 36 | stripped. 37 | 38 | Any lines that are 'more-indented' keep the rest of their indentation - 39 | these lines will be indented by 4 spaces. 40 | folded_style: > 41 | This entire block of text will be the value of 'folded_style', but this 42 | time, all newlines will be replaced with a single space. 43 | 44 | Blank lines, like above, are converted to a newline character. 45 | 46 | 'More-indented' lines keep their newlines, too - 47 | this text will appear over two lines. 48 | 49 | #################### 50 | # 集合类型 # 51 | #################### 52 | 53 | # 嵌套是通过缩进完成的。 54 | a_nested_map: 55 | key: value 56 | another_key: Another Value 57 | another_nested_map: 58 | hello: hello 59 | 60 | # 映射的键值不必是字符串。 61 | 0.25: a float key 62 | 63 | # 键值也可以是复合型的,比如多行对象 64 | # 我们用 ? 后跟一个空格来表示一个复合键的开始。 65 | ? | 66 | This is a key 67 | that has multiple lines 68 | : and this is its value 69 | 70 | # YAML 也允许使用复杂键语法表示序列间的映射关系。 71 | # 但有些语言的解析器可能会不支持。 72 | # 一个例子: 73 | ? - Manchester United 74 | - Real Madrid 75 | : [ 2001-01-01, 2002-02-02 ] 76 | 77 | # 序列 (等价于列表或数组) 看起来像这样: 78 | a_sequence: 79 | - Item 1 80 | - Item 2 81 | - 0.5 # 序列可以包含不同类型。 82 | - Item 4 83 | - key: value 84 | another_key: another_value 85 | - 86 | - This is a sequence 87 | - inside another sequence 88 | 89 | # 因为 YAML 是 JSON 的超集,你也可以写 JSON 风格的映射和序列: 90 | json_map: {"key": "value"} 91 | json_seq: [3, 2, 1, "takeoff"] 92 | 93 | ####################### 94 | # 其余的 YAML 特性 # 95 | ####################### 96 | 97 | # YAML 还有一个方便的特性叫 '锚',它能让你很容易在文档中进行文本复用。 98 | # 如下两个键会有相同的值: 99 | anchored_content: &anchor_name This string will appear as the value of two keys. 100 | other_anchor: *anchor_name 101 | 102 | # 锚也可被用来复制/继承属性 103 | base: &base 104 | name: Everyone has same name 105 | 106 | foo: &foo 107 | <<: *base 108 | age: 10 109 | 110 | bar: &bar 111 | <<: *base 112 | age: 20 113 | 114 | # foo 和 bar 将都含有 name: Everyone has same name 115 | 116 | # YAML 还有标签,你可以用它显示地声明类型。 117 | explicit_string: !!str 0.5 118 | # 一些解析器实现特定语言的标签,就像这个针对 Python 的复数类型。 119 | python_complex_number: !!python/complex 1+2j 120 | 121 | # 我们也可以在 YAML 的复合键中使用特定语言的标签 122 | ? !!python/tuple [5, 7] 123 | : Fifty Seven 124 | # 将会是 Python 中的 {(5, 7): 'Fifty Seven'} 125 | 126 | #################### 127 | # 其余的 YAML 类型 # 128 | #################### 129 | 130 | # 除了字符串和数字,YAML 还能理解其它标量。 131 | # ISO 格式的日期和日期时间文本也可以被解析。 132 | datetime: 2001-12-15T02:59:43.1Z 133 | datetime_with_spaces: 2001-12-14 21:59:43.10 -5 134 | date: 2002-12-14 135 | 136 | # 这个 !!binary 标签表明这个字符串实际上 137 | # 是一个用 base64 编码表示的二进制 blob。 138 | gif_file: !!binary | 139 | R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 140 | OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ 141 | +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC 142 | AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= 143 | 144 | # YAML 还有一个集合类型,它看起来像这样: 145 | set: 146 | ? item1 147 | ? item2 148 | ? item3 149 | 150 | # 像 Python 一样,集合仅是值为 null 的映射;上面的集合等价于: 151 | set2: 152 | item1: null 153 | item2: null 154 | item3: null 155 | ``` 156 | 157 | ### 更多资源 158 | 159 | + [YAML official website](http://yaml.org/) 160 | + [Online YAML Validator](http://codebeautify.org/yaml-validator) 161 | -------------------------------------------------------------------------------- /Frontend/jQuery.md: -------------------------------------------------------------------------------- 1 | # jQuery 2 | 3 | jQuery 是 JavaScript 的一个函数库,它可以帮你“写更少,做更多”。它集成了很多常见的 JavaScript 任务并且很容易调用。jQuery 被世界各地的很多的大公司和开发者使用。它包括了 AJAX,事件处理,文档操作以及很多其它功能,并且更加简单和快速。 4 | 5 | 正因为 jQuery 是 JavaScript 的一个函数库,所以你需要[首先学习 JavaScript](https://learnxinyminutes.com/docs/javascript/) 6 | 7 | ```js 8 | 9 | 10 | /////////////////////////////////// 11 | // 1. 选择器 12 | 13 | // jQuery中的选择器被用来选择一个元素 14 | var page = $(window); // 选择整个视窗 15 | 16 | // 选择器可以作为CSS选择器使用 17 | var paragraph = $('p'); // 选择所有段落元素 18 | var table1 = $('#table1'); // 选择id为table1的元素 19 | var squares = $('.square'); // 选择所有类是square的元素 20 | var square_p = $('p.square') // 选择具有square类的所有段落 21 | 22 | 23 | /////////////////////////////////// 24 | // 2. 事件和效果 25 | // jQuery非常善于处理当事件触发的时候应该做什么 26 | // 一个非常常见的事件就是文档的就绪事件 27 | // 你可以用ready方法,在所有元素完成加载的时候执行 28 | $(document).ready(function(){ 29 | // 只有文档加载完成以后代码才会执行 30 | }); 31 | // 你也可以用定义了的函数 32 | function onAction() { 33 | // 本函数在事件触发的时候被执行 34 | } 35 | $('#btn').click(onAction); // 当点击的时候调用onAction函数 36 | 37 | // 其它常见的事件: 38 | $('#btn').dblclick(onAction); // 双击 39 | $('#btn').hover(onAction); // 划过 40 | $('#btn').focus(onAction); // 聚焦 41 | $('#btn').blur(onAction); // 失焦 42 | $('#btn').submit(onAction); // 提交 43 | $('#btn').select(onAction); // 当元素被选中 44 | $('#btn').keydown(onAction); // 当一个按键被按下 45 | $('#btn').keyup(onAction); // 当一个按键被抬起 46 | $('#btn').keypress(onAction); // 当一个按键被按住 47 | $('#btn').mousemove(onAction); // 当鼠标在移动 48 | $('#btn').mouseenter(onAction); // 鼠标移入元素 49 | $('#btn').mouseleave(onAction); // 鼠标离开元素 50 | 51 | 52 | // 如果不提供任何参数的话,那么这些方法可以触发事件 53 | // 而不是定义处理事件的方法 54 | $('#btn').dblclick(); // 触发元素上的双击 55 | 56 | // 你可以只用选择器一次而处理多个事件 57 | $('#btn').on( 58 | {dblclick: myFunction1} // 双击的时候触发 59 | {blur: myFunction1} // 失焦的时候触发 60 | ); 61 | 62 | // 你可以用一些效果函数来移动或隐藏元素 63 | $('.table').hide(); // 隐藏元素 64 | 65 | // 注意:在这些方法中调用函数会仍然隐藏元素 66 | $('.table').hide(function(){ 67 | // 元素先隐藏然后函数被执行 68 | }); 69 | 70 | // 你可以在变量中储存选择器 71 | var tables = $('.table'); 72 | 73 | // 一些基本的文档操作方法有: 74 | tables.hide(); // 隐藏元素 75 | tables.show(); // 显示元素 76 | tables.toggle(); // 对被选元素进行隐藏和显示的切换 77 | tables.fadeOut(); // 淡出 78 | tables.fadeIn(); // 淡入 79 | tables.fadeToggle(); // 对被选元素进行淡入和淡出显示的切换 80 | tables.fadeTo(0.5); // 把被选元素逐渐改变至给定的不透明度(0和1之间) 81 | tables.slideUp(); // 通过调整高度来滑动隐藏被选元素 82 | tables.slideDown(); // 对被选元素进行滑动隐藏和滑动显示的切换 83 | tables.slideToggle(); // 对被选元素进行滑动隐藏和滑动显示的切换 84 | 85 | // 上面所有的方法接受速度参数(毫秒)和一个回调函数 86 | tables.hide(1000, myFunction); // 持续一秒的隐藏动画然后执行函数 87 | 88 | // fadeTo要求提供透明度参数作为第二个参数 89 | tables.fadeTo(2000, 0.1, myFunction); // 通过2秒钟将透明度变为0.1然后执行函数 90 | 91 | // 你可以用animate方法实现一些略微高级的效果 92 | tables.animate({margin-top:"+=50", height: "100px"}, 500, myFunction); 93 | // animate方法接受一个包含CSS和值的对象作为目标, 94 | // 其次是可选的速度参数, 95 | // 以及最后的回调函数 96 | 97 | /////////////////////////////////// 98 | // 3. 操作 99 | 100 | // 这些类似效果函数但是可以做更多 101 | $('div').addClass('taming-slim-20'); // 给所有div添加类taming-slim-20 102 | 103 | // 常见操作方法 104 | $('p').append('Hello world'); // 添加到元素末尾 105 | $('p').attr('class'); // 获取属性 106 | $('p').attr('class', 'content'); // 设置属性 107 | $('p').hasClass('taming-slim-20'); // 如果有类则为真 108 | $('p').height(); // 获取和设置元素的高度 109 | 110 | 111 | // 对于很多的操作函数来说,获取元素的信息 112 | // 仅仅是第一个符合元素的 113 | $('p').height(); // 仅仅获取第一个p标签的高度 114 | 115 | // 你可以用each来迭代所有元素 116 | var heights = []; 117 | $('p').each(function() { 118 | heights.push($(this).height()); // 把所有p标签的高度加入数组 119 | }); 120 | 121 | 122 | ``` 123 | -------------------------------------------------------------------------------- /Git/Git.md: -------------------------------------------------------------------------------- 1 | # Git 2 | 3 | Git 是一个分布式版本控制及源代码管理工具 4 | 5 | Git 可以为你的项目保存若干快照,以此来对整个项目进行版本管理 6 | 7 | ## 版本 8 | 9 | ### 什么是版本控制 10 | 11 | 版本控制系统就是根据时间来记录一个或多个文件的更改情况的系统。 12 | 13 | ### 集中式版本控制 VS 分布式版本控制 14 | 15 | * 集中式版本控制的主要功能为同步,跟踪以及备份文件 16 | * 分布式版本控制则更注重共享更改。每一次更改都有唯一的标识 17 | * 分布式系统没有预定的结构。你也可以用 git 很轻松的实现 SVN 风格的集中式系统控制 18 | 19 | [更多信息](http://git-scm.com/book/en/Getting-Started-About-Version-Control) 20 | 21 | ### 为什么要使用 Git 22 | 23 | * 可以离线工作 24 | * 和他人协同工作变得简单 25 | * 分支很轻松 26 | * 合并很容易 27 | * Git 系统速度快,也很灵活 28 | 29 | ## Git 架构 30 | 31 | 32 | ### 版本库 33 | 34 | 一系列文件,目录,历史记录,提交记录和头指针。 35 | 可以把它视作每个源代码文件都带有历史记录属性数据结构 36 | 37 | 一个 Git 版本库包括一个 .git 目录和其工作目录 38 | 39 | ### .git 目录(版本库的一部分) 40 | 41 | .git 目录包含所有的配置、日志、分支信息、头指针等 42 | [详细列表](http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html) 43 | 44 | ### 工作目录 (版本库的一部分) 45 | 46 | 版本库中的目录和文件,可以看做就是你工作时的目录 47 | 48 | ### 索引(.git 目录) 49 | 50 | 索引就是 git 中的 staging 区. 可以算作是把你的工作目录与 Git 版本库分割开的一层 51 | 这使得开发者能够更灵活的决定要将要在版本库中添加什么内容 52 | 53 | ### 提交 54 | 55 | 一个 git 提交就是一组更改或者对工作目录操作的快照 56 | 比如你添加了 5 个文件,删除了 2 个文件,那么这些变化就会被写入一个提交比如你添加了 5 个文件,删除了 2 个文件,那么这些变化就会被写入一个提交中 57 | 而这个提交之后也可以被决定是否推送到另一个版本库中 58 | 59 | ### 分支 60 | 61 | 分支其实就是一个指向你最后一次的提交的指针 62 | 当你提交时,这个指针就会自动指向最新的提交 63 | 64 | ### 头指针 与 头(.git 文件夹的作用) 65 | 66 | 头指针是一个指向当前分支的指针,一个版本库只有一个当前活动的头指针 67 | 而头则可以指向版本库中任意一个提交,每个版本库也可以有多个头 68 | 69 | ### 其他形象化解释 70 | 71 | * [给计算机科学家的解释](http://eagain.net/articles/git-for-computer-scientists/) 72 | * [给设计师的解释](http://hoth.entp.com/output/git_for_designers.html) 73 | 74 | 75 | ## 命令 76 | 77 | 78 | ### 初始化 79 | 80 | 创建一个新的 git 版本库。这个版本库的配置、存储等信息会被保存到.git 文件夹中 81 | 82 | ```bash 83 | $ git init 84 | ``` 85 | 86 | ### 配置 87 | 88 | 更改设置。可以是版本库的设置,也可以是系统的或全局的 89 | 90 | 91 | ```bash 92 | # 输出、设置基本的全局变量 93 | $ git config --global user.email 94 | $ git config --global user.name 95 | 96 | $ git config --global user.email "MyEmail@Zoho.com" 97 | $ git config --global user.name "My Name" 98 | ``` 99 | 100 | [关于 git 的更多设置](http://git-scm.com/docs/git-config) 101 | 102 | ### 帮助 103 | 104 | git 内置了对命令非常详细的解释,可以供我们快速查阅 105 | 106 | ```bash 107 | # 查找可用命令 108 | $ git help 109 | 110 | # 查找所有可用命令 111 | $ git help -a 112 | 113 | # 在文档当中查找特定的命令 114 | # git help <命令> 115 | $ git help add 116 | $ git help commit 117 | $ git help init 118 | ``` 119 | 120 | ### 状态 121 | 122 | 显示索引文件(也就是当前工作空间)和当前的头指针指向的提交的不同 123 | 124 | 125 | ```bash 126 | # 显示分支,未跟踪文件,更改和其他不同 127 | $ git status 128 | 129 | # 查看其他的git status的用法 130 | $ git help status 131 | ``` 132 | 133 | ### 添加 134 | 135 | 添加文件到当前工作空间中。如果你不使用 `git add` 将文件添加进去, 136 | 那么这些文件也不会添加到之后的提交之中 137 | 138 | ```bash 139 | # 添加一个文件 140 | $ git add HelloWorld.java 141 | 142 | # 添加一个子目录中的文件 143 | $ git add /path/to/file/HelloWorld.c 144 | 145 | # 支持正则表达式 146 | $ git add ./*.java 147 | ``` 148 | 149 | ### 分支 150 | 151 | 管理分支,可以通过下列命令对分支进行增删改查 152 | 153 | ```bash 154 | # 查看所有的分支和远程分支 155 | $ git branch -a 156 | 157 | # 创建一个新的分支 158 | $ git branch myNewBranch 159 | 160 | # 删除一个分支 161 | $ git branch -d myBranch 162 | 163 | # 重命名分支 164 | # git branch -m <旧名称> <新名称> 165 | $ git branch -m myBranchName myNewBranchName 166 | 167 | # 编辑分支的介绍 168 | $ git branch myBranchName --edit-description 169 | ``` 170 | 171 | ### 检出 172 | 173 | 将当前工作空间更新到索引所标识的或者某一特定的工作空间 174 | 175 | ```bash 176 | # 检出一个版本库,默认将更新到master分支 177 | $ git checkout 178 | # 检出到一个特定的分支 179 | $ git checkout branchName 180 | # 新建一个分支,并且切换过去,相当于"git branch <名字>; git checkout <名字>" 181 | $ git checkout -b newBranch 182 | ``` 183 | 184 | ### clone 185 | 186 | 这个命令就是将一个版本库拷贝到另一个目录中,同时也将 187 | 分支都拷贝到新的版本库中。这样就可以在新的版本库中提交到远程分支 188 | 189 | ```bash 190 | # clone learnxinyminutes-docs 191 | $ git clone https://github.com/adambard/learnxinyminutes-docs.git 192 | ``` 193 | 194 | ### commit 195 | 196 | 将当前索引的更改保存为一个新的提交,这个提交包括用户做出的更改与信息 197 | 198 | ```bash 199 | # 提交时附带提交信息 200 | $ git commit -m "Added multiplyNumbers() function to HelloWorld.c" 201 | ``` 202 | 203 | ### diff 204 | 205 | 显示当前工作空间和提交的不同 206 | 207 | ```bash 208 | # 显示工作目录和索引的不同 209 | $ git diff 210 | 211 | # 显示索引和最近一次提交的不同 212 | $ git diff --cached 213 | 214 | # 显示工作目录和最近一次提交的不同 215 | $ git diff HEAD 216 | ``` 217 | 218 | ### grep 219 | 220 | 可以在版本库中快速查找 221 | 222 | 可选配置: 223 | 224 | ```bash 225 | # 感谢Travis Jeffery提供的以下用法: 226 | # 在搜索结果中显示行号 227 | $ git config --global grep.lineNumber true 228 | 229 | # 是搜索结果可读性更好 230 | $ git config --global alias.g "grep --break --heading --line-number" 231 | ``` 232 | 233 | ```bash 234 | # 在所有的java中查找variableName 235 | $ git grep 'variableName' -- '*.java' 236 | 237 | # 搜索包含 "arrayListName" 和, "add" 或 "remove" 的所有行 238 | $ git grep -e 'arrayListName' --and \( -e add -e remove \) 239 | ``` 240 | 241 | 更多的例子可以查看: 242 | [Git Grep Ninja](http://travisjeffery.com/b/2012/02/search-a-git-repo-like-a-ninja) 243 | 244 | ### log 245 | 246 | 显示这个版本库的所有提交 247 | 248 | ```bash 249 | # 显示所有提交 250 | $ git log 251 | 252 | # 显示某几条提交信息 253 | $ git log -n 10 254 | 255 | # 仅显示合并提交 256 | $ git log --merges 257 | ``` 258 | 259 | ### merge 260 | 261 | 合并就是将外部的提交合并到自己的分支中 262 | 263 | ```bash 264 | # 将其他分支合并到当前分支 265 | $ git merge branchName 266 | 267 | # 在合并时创建一个新的合并后的提交 268 | $ git merge --no-ff branchName 269 | ``` 270 | 271 | ### mv 272 | 273 | 重命名或移动一个文件 274 | 275 | ```bash 276 | # 重命名 277 | $ git mv HelloWorld.c HelloNewWorld.c 278 | 279 | # 移动 280 | $ git mv HelloWorld.c ./new/path/HelloWorld.c 281 | 282 | # 强制重命名或移动 283 | # 这个文件已经存在,将要覆盖掉 284 | $ git mv -f myFile existingFile 285 | ``` 286 | 287 | ### pull 288 | 289 | 从远端版本库合并到当前分支 290 | 291 | ```bash 292 | # 从远端origin的master分支更新版本库 293 | # git pull <远端> <分支> 294 | $ git pull origin master 295 | ``` 296 | 297 | ### push 298 | 299 | 把远端的版本库更新 300 | 301 | ```bash 302 | # 把本地的分支更新到远端origin的master分支上 303 | # git push <远端> <分支> 304 | # git push 相当于 git push origin master 305 | $ git push origin master 306 | ``` 307 | 308 | ### rebase (谨慎使用) 309 | 310 | 将一个分支上所有的提交历史都应用到另一个分支上 311 | *不要在一个已经公开的远端分支上使用 rebase*. 312 | 313 | ```bash 314 | # 将experimentBranch应用到master上面 315 | # git rebase 316 | $ git rebase master experimentBranch 317 | ``` 318 | 319 | [更多阅读](http://git-scm.com/book/en/Git-Branching-Rebasing) 320 | 321 | ### reset (谨慎使用) 322 | 323 | 将当前的头指针复位到一个特定的状态。这样可以使你撤销 merge、pull、commits、add 等 324 | 这是个很强大的命令,但是在使用时一定要清楚其所产生的后果 325 | 326 | ```bash 327 | # 使 staging 区域恢复到上次提交时的状态,不改变现在的工作目录 328 | $ git reset 329 | 330 | # 使 staging 区域恢复到上次提交时的状态,覆盖现在的工作目录 331 | $ git reset --hard 332 | 333 | # 将当前分支恢复到某次提交,不改变现在的工作目录 334 | # 在工作目录中所有的改变仍然存在 335 | $ git reset 31f2bb1 336 | 337 | # 将当前分支恢复到某次提交,覆盖现在的工作目录 338 | # 并且删除所有未提交的改变和指定提交之后的所有提交 339 | $ git reset --hard 31f2bb1 340 | ``` 341 | 342 | ### rm 343 | 344 | 和 add 相反,从工作空间中去掉某个文件 345 | 346 | ```bash 347 | # 移除 HelloWorld.c 348 | $ git rm HelloWorld.c 349 | 350 | # 移除子目录中的文件 351 | $ git rm /pather/to/the/file/HelloWorld.c 352 | ``` 353 | 354 | ## 更多阅读 355 | 356 | * [tryGit - 学习 Git 的有趣方式](http://try.github.io/levels/1/challenges/1) 357 | 358 | * [git-scm - 视频教程](http://git-scm.com/videos) 359 | 360 | * [git-scm - 文档](http://git-scm.com/docs) 361 | 362 | * [Atlassian Git - 教程与工作流程](https://www.atlassian.com/git/) 363 | 364 | * [SalesForce Cheat Sheet](https://na1.salesforce.com/help/doc/en/salesforce_git_developer_cheatsheet.pdf) 365 | 366 | * [GitGuys](http://www.gitguys.com/) 367 | -------------------------------------------------------------------------------- /Git/git-commit-message-change-log.md: -------------------------------------------------------------------------------- 1 | # git commit message 和 Change log 2 | 3 | ## Commit message 的格式 4 | 5 | 每次提交,Commit message 都包括三个部分:Header,Body 和 Footer。 6 | 7 | ```plain 8 | (): 9 | // 空一行 10 | 11 | // 空一行 12 |
13 | ``` 14 | 15 | 其中,`Header` 是必需的,`Body` 和 `Footer` 可以省略。 16 | 不管是哪一个部分,任何一行都不得超过 _72_ 个字符(或 _100_ 个字符)。这是为了避免自动换行影响美观。 17 | 18 | ### Header 19 | 20 | Header 部分只有一行,包括三个字段:`type`(必需)、`scope`(可选)和`subject`(必需)。 21 | 22 | * **`type`** 23 | 24 | `type`用于说明`commit`的类别,只允许使用下面 7 个标识。 25 | 26 | > 1. `feat` 新功能(feature) 27 | > 2. `fix` 修补 bug 28 | > 3. `docs` 文档(documentation) 29 | > 4. `style` 格式(不影响代码运行的变动) 30 | > 5. `ref` 重构(即不是新增功能,也不是修改 bug 的代码变动) 31 | > 6. `test` 增加测试 32 | > 7. `chore` 构建过程或辅助工具的变动 33 | 34 | 如果`type`为`feat`和`fix`,则该`commit`将肯定出现在`Change log`之中。其他情况(`docs`、`chore`、`style`、`refactor`、`test`)由你决定,要不要放入`Change log`,**建议是不要**。 35 | 36 | * **`scope`** `scope`用于说明`commit`影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同。 37 | 38 | * **`subject`** `subject`是`commit`目的的简短描述,不超过 _50_ 个字符。 39 | 40 | > 1. 以动词开头,使用第一人称现在时,比如`change`,而不是 ~~`changed`~~或 ~~`changes`~~ 41 | > 42 | > 43 | > 2. 第一个字母小写 44 | > 45 | > 46 | > 3. 结尾不加句号(.) 47 | 48 | ### Body 49 | 50 | Body 部分是对本次 commit 的详细描述,可以分成多行。下面是一个范例。 51 | 52 | ```plain 53 | More detailed explanatory text, if necessary. Wrap it to 54 | about 72 characters or so. 55 | 56 | Further paragraphs come after blank lines. 57 | 58 | - Bullet points are okay, too 59 | - Use a hanging indent 60 | ``` 61 | 62 | 有两个注意点。 63 | 64 | > 1. 使用第一人称现在时,比如使用`change`而不是 ~~`changed`~~或 ~~`changes`~~ 65 | > 2. 应该说明代码变动的动机,以及与以前行为的对比 66 | 67 | ### Footer 68 | 69 | Footer 部分只用于两种情况。 70 | 71 | * 不兼容变动 72 | 如果当前代码与上一个版本不兼容,则`Footer`部分以`BREAKING CHANGE`开头,后面是对变动的描述、以及变动理由和迁移方法。 73 | 74 | ```plain 75 | BREAKING CHANGE: isolate scope bindings definition has changed. 76 | 77 | To migrate the code follow the example below: 78 | 79 | Before: 80 | 81 | scope: { 82 | myAttr: 'attribute', 83 | } 84 | 85 | After: 86 | 87 | scope: { 88 | myAttr: '@', 89 | } 90 | 91 | The removed `inject` wasn't generaly useful for directives so there should be no code using it. 92 | ``` 93 | 94 | * 关闭 Issue 95 | 96 | 如果当前`commit`针对某个`issue`,那么可以在`Footer`部分关闭这个`issue`。 97 | 98 | ```plain 99 | Closes #234 100 | ``` 101 | 102 | 也可以一次关闭多个 issue 。 103 | 104 | ```plain 105 | Closes #123, #245, #992 106 | ``` 107 | 108 | ### Revert 109 | 110 | 还有一种特殊情况,如果当前`commit`用于撤销以前的`commit`,则必须以**`revert:`**开头,后面跟着被撤销`Commit`的`Header`。 111 | 112 | ```plain 113 | revert: feat(pencil): add 'graphiteWidth' option 114 | 115 | This reverts commit 667ecc1654a317a13331b17617d973392f415f02. 116 | ``` 117 | 118 | `Body`部分的格式是固定的,必须写成`This reverts commit `,其中的`hash`是被撤销`commit`的`SHA`标识符。 119 | 120 | 如果当前`commit`与被撤销的`commit`,在同一个发布(`release`)里面,那么它们都不会出现在`Change log`里面。如果两者在不同的发布,那么当前`commit`,会出现在 `Change log`的`Reverts`小标题下面。 121 | 122 | ## Commitizen 123 | 124 | [Commitizen](https://link.jianshu.com?t=https://github.com/commitizen/cz-cli) 是一个撰写合格`Commit message`的工具。 125 | 126 | 安装命令如下。(_遇到缺少 package.json 文件的解决办法在文章最后_) 127 | 128 | ```plain 129 | $ npm install -g commitizen 130 | ``` 131 | 132 | ```plain 133 | $ npm install -g cz-conventional-changelog 134 | ``` 135 | 136 | ```plain 137 | echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc 138 | ``` 139 | 140 | 以后,凡是用到`git commit`命令,一律改为使用`git cz`。这时,就会出现选项,用来生成符合格式的`Commit message`。 141 | 142 | ## 生成 Change log 143 | 144 | 如果你的所有`Commit`都符合`Angular`格式,那么发布新版本时,`Change log`就可以用脚本自动生成(例 1:[karma/CHANGELOG.md](https://link.jianshu.com?t=https://github.com/karma-runner/karma/blob/master/CHANGELOG.md), 例 2:[btford/grunt-conventional-changelog](https://link.jianshu.com?t=https://github.com/btford/grunt-conventional-changelog/blob/master/CHANGELOG.md))。 145 | 146 | 生成的文档包括以下三个部分。 147 | 148 | > * New features 149 | > * Bug fixes 150 | > * Breaking changes 151 | 152 | 每个部分都会罗列相关的`commit`,并且有指向这些`commit`的链接。当然,生成的文档允许手动修改,所以发布前,你还可以添加其他内容。 153 | 154 | [conventional-changelog-cli](https://link.jianshu.com?t=https://github.com/conventional-changelog-archived-repos/conventional-changelog-cli) 就是生成`Change log`的工具,运行下面的命令即可。 155 | 156 | ```plain 157 | $ npm install -g conventional-changelog-cli 158 | $ cd my-project 159 | ``` 160 | 161 | 打印到屏幕 162 | 163 | ```plain 164 | $ conventional-changelog -p angular -i CHANGELOG.md -w 165 | ``` 166 | 167 | 输出到文件 168 | 169 | ```plain 170 | $ conventional-changelog -p angular -i CHANGELOG.md -s 171 | ``` 172 | 173 | 上面命令不会覆盖以前的`Change log`,只会在`CHANGELOG.md`的头部加上自从上次发布以来的变动。 174 | 175 | 如果你想生成所有发布的`Change log`,要改为运行下面的命令。 176 | 177 | ```plain 178 | $ conventional-changelog -p angular -i CHANGELOG.md -s -r 0 179 | ``` 180 | 181 | 为了方便使用,可以将其写入`package.json`的`scripts`字段。 182 | 183 | ```plain 184 | { 185 | "scripts": { 186 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -w -r 0" 187 | } 188 | } 189 | ``` 190 | 191 | 以后,直接运行下面的命令即可。 192 | 193 | ```plain 194 | $ npm run changelog 195 | ``` 196 | 197 | ### 缺少 package.json 文件 198 | 199 | 因为`commitizen`工具是基于 **Node.js** 的,而我们 **iOS** 项目工程目录下是没有`package.json`文件,所以会报错: 200 | 201 | ```plain 202 | Error: ENOENT: no such file or directory, open '/Users/***/package.json 203 | ``` 204 | 205 | 关于这个问题,可以参考这个`commitizen`的 **issue**:[Usage in non-node projects?](https://link.jianshu.com?t=https://github.com/commitizen/cz-cli/issues/102),对于非 Node 的项目,我们可先在我们项目中添加一个空的`package.json`文件,然后再输入命令: 206 | 207 | ```plain 208 | $ npm init --yes 209 | ``` 210 | 211 | 先初始化配置 package.json 文件,然后再输入命令: 212 | 213 | ```plain 214 | $ commitizen init cz-conventional-changelog --save --save-exact 215 | ``` 216 | 217 | ## 参考链接 218 | 219 | * [Commit message 和 Change log 编写指南](http://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html) 220 | -------------------------------------------------------------------------------- /Git/常用Git命令清单.md: -------------------------------------------------------------------------------- 1 | # 常用 Git 命令清单 2 | 3 | ## [Git Commit message 和 Change log 编写指南](http://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html) 4 | 5 | ## [Commitizen 的安装和使用](https://www.jianshu.com/p/d264f88d13a4) 6 | 7 | ## 新建代码库 8 | 9 | ``` bash 10 | # 在当前目录新建一个Git代码库 11 | $ git init 12 | 13 | # 新建一个目录,将其初始化为Git代码库 14 | $ git init [project-name] 15 | 16 | # 下载一个项目和它的整个代码历史 17 | $ git clone [url] 18 | ``` 19 | 20 | ## 配置 21 | 22 | Git 的设置文件为`.gitconfig`,它可以在用户主目录下(全局配置),也可以在项目目录下(项目配置)。 23 | 24 | ``` bash 25 | # 显示当前的Git配置 26 | $ git config --list 27 | 28 | # 编辑Git配置文件 29 | $ git config -e [--global] 30 | 31 | # 设置提交代码时的用户信息 32 | $ git config [--global] user.name "[name]" 33 | $ git config [--global] user.email "[email address]" 34 | ``` 35 | 36 | ## 增加 / 删除文件 37 | 38 | ``` bash 39 | # 添加指定文件到暂存区 40 | $ git add [file1] [file2] ... 41 | 42 | # 添加指定目录到暂存区,包括子目录 43 | $ git add [dir] 44 | 45 | # 添加当前目录的所有文件到暂存区 46 | $ git add . 47 | 48 | # 添加每个变化前,都会要求确认 49 | # 对于同一个文件的多处变化,可以实现分次提交 50 | $ git add -p 51 | 52 | # 删除工作区文件,并且将这次删除放入暂存区 53 | $ git rm [file1] [file2] ... 54 | 55 | # 停止追踪指定文件,但该文件会保留在工作区 56 | $ git rm --cached [file] 57 | 58 | # 改名文件,并且将这个改名放入暂存区 59 | $ git mv [file-original] [file-renamed] 60 | ``` 61 | 62 | ## 代码提交 63 | 64 | ``` bash 65 | # 提交暂存区到仓库区 66 | $ git commit -m [message] 67 | 68 | # 提交暂存区的指定文件到仓库区 69 | $ git commit [file1] [file2] ... -m [message] 70 | 71 | # 提交工作区自上次commit之后的变化,直接到仓库区 72 | $ git commit -a 73 | 74 | # 提交时显示所有diff信息 75 | $ git commit -v 76 | 77 | # 使用一次新的commit,替代上一次提交 78 | # 如果代码没有任何新变化,则用来改写上一次commit的提交信息 79 | $ git commit --amend -m [message] 80 | 81 | # 重做上一次commit,并包括指定文件的新变化 82 | $ git commit --amend [file1] [file2] ... 83 | ``` 84 | 85 | ## 分支 86 | 87 | ``` bash 88 | # 列出所有本地分支 89 | $ git branch 90 | 91 | # 列出所有远程分支 92 | $ git branch -r 93 | 94 | # 列出所有本地分支和远程分支 95 | $ git branch -a 96 | 97 | # 新建一个分支,但依然停留在当前分支 98 | $ git branch [branch-name] 99 | 100 | # 新建一个分支,并切换到该分支 101 | $ git checkout -b [branch] 102 | 103 | # 新建一个分支,指向指定commit 104 | $ git branch [branch] [commit] 105 | 106 | # 新建一个分支,与指定的远程分支建立追踪关系 107 | $ git branch --track [branch] [remote-branch] 108 | 109 | # 切换到指定分支,并更新工作区 110 | $ git checkout [branch-name] 111 | 112 | # 切换到上一个分支 113 | $ git checkout - 114 | 115 | # 建立追踪关系,在现有分支与指定的远程分支之间 116 | $ git branch --set-upstream [branch] [remote-branch] 117 | 118 | # 合并指定分支到当前分支 119 | $ git merge [branch] 120 | 121 | # 选择一个commit,合并进当前分支 122 | $ git cherry-pick [commit] 123 | 124 | # 删除分支 125 | $ git branch -d [branch-name] 126 | 127 | # 删除远程分支 128 | $ git push origin --delete [branch-name] 129 | $ git branch -dr [remote/branch] 130 | ``` 131 | 132 | ## 标签 133 | 134 | ``` bash 135 | # 列出所有tag 136 | $ git tag 137 | 138 | # 新建一个tag在当前commit 139 | $ git tag [tag] 140 | 141 | # 新建一个tag在指定commit 142 | $ git tag [tag] [commit] 143 | 144 | # 删除本地tag 145 | $ git tag -d [tag] 146 | 147 | # 删除远程tag 148 | $ git push origin :refs/tags/[tagName] 149 | 150 | # 查看tag信息 151 | $ git show [tag] 152 | 153 | # 提交指定tag 154 | $ git push [remote] [tag] 155 | 156 | # 提交所有tag 157 | $ git push [remote] --tags 158 | 159 | # 新建一个分支,指向某个tag 160 | $ git checkout -b [branch] [tag] 161 | ``` 162 | 163 | ## 查看信息 164 | 165 | ``` bash 166 | # 显示有变更的文件 167 | $ git status 168 | 169 | # 显示当前分支的版本历史 170 | $ git log 171 | 172 | # 显示commit历史,以及每次commit发生变更的文件 173 | $ git log --stat 174 | 175 | # 搜索提交历史,根据关键词 176 | $ git log -S [keyword] 177 | 178 | # 显示某个commit之后的所有变动,每个commit占据一行 179 | $ git log [tag] HEAD --pretty=format:%s 180 | 181 | # 显示某个commit之后的所有变动,其"提交说明"必须符合搜索条件 182 | $ git log [tag] HEAD --grep feature 183 | 184 | # 显示某个文件的版本历史,包括文件改名 185 | $ git log --follow [file] 186 | $ git whatchanged [file] 187 | 188 | # 显示指定文件相关的每一次diff 189 | $ git log -p [file] 190 | 191 | # 显示过去5次提交 192 | $ git log -5 --pretty --oneline 193 | 194 | # 显示所有提交过的用户,按提交次数排序 195 | $ git shortlog -sn 196 | 197 | # 显示指定文件是什么人在什么时间修改过 198 | $ git blame [file] 199 | 200 | # 显示暂存区和工作区的差异 201 | $ git diff 202 | 203 | # 显示暂存区和上一个commit的差异 204 | $ git diff --cached [file] 205 | 206 | # 显示工作区与当前分支最新commit之间的差异 207 | $ git diff HEAD 208 | 209 | # 显示两次提交之间的差异 210 | $ git diff [first-branch]...[second-branch] 211 | 212 | # 显示今天你写了多少行代码 213 | $ git diff --shortstat "@{0 day ago}" 214 | 215 | # 显示某次提交的元数据和内容变化 216 | $ git show [commit] 217 | 218 | # 显示某次提交发生变化的文件 219 | $ git show --name-only [commit] 220 | 221 | # 显示某次提交时,某个文件的内容 222 | $ git show [commit]:[filename] 223 | 224 | # 显示当前分支的最近几次提交 225 | $ git reflog 226 | ``` 227 | 228 | ## 远程同步 229 | 230 | ``` bash 231 | # 下载远程仓库的所有变动 232 | $ git fetch [remote] 233 | 234 | # 显示所有远程仓库 235 | $ git remote -v 236 | 237 | # 显示某个远程仓库的信息 238 | $ git remote show [remote] 239 | 240 | # 增加一个新的远程仓库,并命名 241 | $ git remote add [shortname] [url] 242 | 243 | # 取回远程仓库的变化,并与本地分支合并 244 | $ git pull [remote] [branch] 245 | 246 | # 上传本地指定分支到远程仓库 247 | $ git push [remote] [branch] 248 | 249 | # 强行推送当前分支到远程仓库,即使有冲突 250 | $ git push [remote] --force 251 | 252 | # 推送所有分支到远程仓库 253 | $ git push [remote] --all 254 | ``` 255 | 256 | ## 撤销 257 | 258 | ``` bash 259 | # 恢复暂存区的指定文件到工作区 260 | $ git checkout [file] 261 | 262 | # 恢复某个commit的指定文件到暂存区和工作区 263 | $ git checkout [commit] [file] 264 | 265 | # 恢复暂存区的所有文件到工作区 266 | $ git checkout . 267 | 268 | # 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变 269 | $ git reset [file] 270 | 271 | # 重置暂存区与工作区,与上一次commit保持一致 272 | $ git reset --hard 273 | 274 | # 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变 275 | $ git reset [commit] 276 | 277 | # 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致 278 | $ git reset --hard [commit] 279 | 280 | # 重置当前HEAD为指定commit,但保持暂存区和工作区不变 281 | $ git reset --keep [commit] 282 | 283 | # 新建一个commit,用来撤销指定commit 284 | # 后者的所有变化都将被前者抵消,并且应用到当前分支 285 | $ git revert [commit] 286 | 287 | # 暂时将未提交的变化移除,稍后再移入 288 | $ git stash 289 | $ git stash pop 290 | ``` 291 | 292 | ## 其他 293 | 294 | ``` bash 295 | # 生成一个可供发布的压缩包 296 | $ git archive 297 | ``` 298 | 299 | ## 相关链接 300 | 301 | * [http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html](http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html) 302 | -------------------------------------------------------------------------------- /Go/Go.md: -------------------------------------------------------------------------------- 1 | # Go 2 | 3 | ## 最佳实践和建议 4 | 5 | * 尽可能的使用:=去初始化声明一个变量(在函数内部) 6 | * 尽可能的使用字符代替字符串 7 | * 尽可能的使用切片代替数组 8 | * 尽可能的使用数组和切片代替映射 9 | * 如果只想获取切片中某项值,不需要值的索引,尽可能的使用 for range 去遍历切片,这比必须查询切片中的每个元素要快一些 10 | * 当数组元素是稀疏的(例如有很多 0 值或者空值 nil),使用映射会降低内存消耗 11 | * 初始化映射时指定其容量 12 | * 当定义一个方法时,使用指针类型作为方法的接受者 13 | * 在代码中使用常量或者标志提取常量的值 14 | * 尽可能在需要分配大量内存时使用缓存 15 | * 使用缓存模板 16 | 17 | ## 常见的陷阱与错误 18 | 19 | * 永远不要使用形如 `var p*a` 声明变量,这会混淆指针声明和乘法运算 20 | * 永远不要在`for`循环自身中改变计数器变量 21 | * 永远不要在`for-range`循环中使用一个值去改变自身的值 22 | * 永远不要将`goto`和前置标签一起使用 23 | * 永远不要忘记在函数名后加括号 (),尤其调用一个对象的方法或者使用匿名函数启动一个协程时 24 | * 永远不要使用`new()`一个 map,一直使用 make 25 | * 当为一个类型定义一个 String() 方法时,不要使用`fmt.Print`或者类似的代码 26 | * 永远不要忘记当终止缓存写入时,使用`Flush`函数 27 | * 永远不要忽略错误提示,忽略错误会导致程序奔溃 28 | * 不要使用全局变量或者共享内存,这会使并发执行的代码变得不安全 29 | * `println`函数仅仅是用于调试的目的 30 | -------------------------------------------------------------------------------- /Go/golang.go: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Golang CHEATSHEET (中文速查表) - by chlins (created on 2018/02/14) 3 | * Version: 3, Last Modified: 2018/03/07 19:51 4 | * https://github.com/skywind3000/awesome-cheatsheets 5 | ******************************************************************************/ 6 | 7 | 8 | 9 | /****************************************************************************** 10 | * Go 编译器命令 11 | *****************************************************************************/ 12 | go command [arguments] // go 命令 [参数] 13 | go build // 编译包和依赖包 14 | go clean // 移除对象和缓存文件 15 | go doc // 显示包的文档 16 | go env // 打印go的环境变量信息 17 | go bug // 报告bug 18 | go fix // 更新包使用新的api 19 | go fmt // 格式规范化代码 20 | go generate // 通过处理资源生成go文件 21 | go get // 下载并安装包及其依赖 22 | go install // 编译和安装包及其依赖 23 | go list // 列出所有包 24 | go run // 编译和运行go程序 25 | go test // 测试 26 | go tool // 运行给定的go工具 27 | go version // 显示go当前版本 28 | go vet // 发现代码中可能的错误 29 | 30 | 31 | 32 | /******************************************************************************* 33 | * Hello World 34 | ******************************************************************************/ 35 | // main.go 36 | package main // 包名 37 | 38 | import "fmt" // 导入fmt包 39 | 40 | func main() { // 主函数 41 | fmt.Println("Hello World") // 打印输出 42 | } 43 | // go run main.go // 直接运行 44 | // go build && ./main // 先编译成二进制文件再运行 45 | 46 | 47 | 48 | /******************************************************************************* 49 | * 操作符 50 | ******************************************************************************/ 51 | // 算数操作符 52 | + - * / % // 加 减 乘 除 取余 53 | & | ^ &^ // 位与 位或 位异或 位与非 54 | << >> // 左移 右移 55 | // 比较操作 56 | == != // 等于 不等于 57 | < <= // 小于 小于等于 58 | > >= // 大于 大于等于 59 | // 逻辑操作 60 | && || ! // 逻辑与 逻辑或 逻辑非 61 | // 其他 62 | & * <- // 地址 指针引用 通道操作 63 | 64 | 65 | 66 | /******************************************************************************* 67 | * 声明 68 | ******************************************************************************/ 69 | a := 1 // 直接给一个未声明的变量赋值 70 | var b int // var 变量名 数据类型 来声明 71 | var c float64 72 | // 注意:使用var声明过的变量不可再使用 := 赋值 73 | a = 2 74 | const d = 1 // 常量 75 | 76 | 77 | 78 | 79 | /******************************************************************************* 80 | * 数据类型 81 | ******************************************************************************/ 82 | s := "hello" // 字符 83 | a := 1 // int 84 | b := 1.2 // float64 85 | c := 1 + 5i // complex128 86 | // 数组 87 | arr1 := [3]int{4, 5, 6} // 手动指定长度 88 | arr2 := [...]int{1, 2, 3} // 由golang自动计算长度 89 | // 切片 90 | sliceInt := []int{1, 2} // 不指定长度 91 | sliceByte := []byte("hello") 92 | // 指针 93 | a := 1 94 | point := &a // 将a的地址赋给point 95 | 96 | 97 | /******************************************************************************* 98 | * 流程控制 99 | ******************************************************************************/ 100 | // for 101 | i := 10 102 | for i > 0 { 103 | println(i--) 104 | } 105 | // if else 106 | if i == 10 { 107 | println("i == 10") 108 | } else { 109 | println("i != 10") 110 | } 111 | // switch 112 | switch i { 113 | case 10: 114 | println("i == 10") 115 | default: 116 | println("i != 10") 117 | } 118 | 119 | 120 | /******************************************************************************* 121 | * 函数 122 | ******************************************************************************/ 123 | // 以func关键字声明 124 | func test() {} 125 | 126 | f := func() {println("Lambdas function")} // 匿名函数 127 | f() 128 | 129 | func get() (a,b string) { // 函数多返回值 130 | return "a", "b" 131 | } 132 | a, b := get() 133 | 134 | 135 | 136 | 137 | /******************************************************************************* 138 | * 结构体 139 | ******************************************************************************/ 140 | // golang中没有class只有struct 141 | type People struct { 142 | Age int // 大写开头的变量在包外可以访问 143 | name string // 小写开头的变量仅可在本包内访问 144 | } 145 | p1 := People{25, "Kaven"} // 必须按照结构体内部定义的顺序 146 | p2 := People{name: "Kaven", age: 25} // 若不按顺序则需要指定字段 147 | 148 | // 也可以先不赋值 149 | p3 := new(People) 150 | p3.Age = 25 151 | p3.name = "Kaven" 152 | 153 | 154 | /******************************************************************************* 155 | * 方法 156 | ******************************************************************************/ 157 | // 方法通常是针对一个结构体来说的 158 | type Foo struct { 159 | a int 160 | } 161 | // 值接收者 162 | func (f Foo) test() { 163 | f.a = 1 // 不会改变原来的值 164 | } 165 | // 指针接收者 166 | func (f *Foo) test() { 167 | f.a = 1 // 会改变原值 168 | } 169 | 170 | 171 | 172 | /******************************************************************************* 173 | * go 协程 174 | ******************************************************************************/ 175 | go func() { 176 | time.Sleep(10 * time.Second) 177 | println("hello") 178 | }() // 不会阻塞代码的运行 代码会直接向下运行 179 | // channel 通道 180 | c := make(chan int) 181 | // 两个协程间可以通过chan通信 182 | go func() {c <- 1}() // 此时c会被阻塞 直到值被取走前都不可在塞入新值 183 | go func() {println(<-c)}() 184 | // 带缓存的channel 185 | bc := make(chan int, 2) 186 | go func() {c <- 1; c <-2}() // c中可以存储声明时所定义的缓存大小的数据,这里是2个 187 | go func() {println(<-c)}() 188 | 189 | 190 | 191 | /******************************************************************************* 192 | * 接口 193 | ******************************************************************************/ 194 | // go的接口为鸭子类型,即只要你实现了接口中的方法就实现了该接口 195 | type Reader interface { 196 | Reading() // 仅需实现Reading方法就实现了该接口 197 | } 198 | 199 | type As struct {} 200 | func (a As) Reading() {} // 实现了Reader接口 201 | 202 | type Bs struct {} 203 | func (b Bs) Reading() {} // 也实现了Reader接口 204 | func (b Bs) Closing() {} 205 | 206 | 207 | 208 | 209 | /******************************************************************************* 210 | * 一些推荐 211 | ******************************************************************************/ 212 | // 入门书籍 213 | 《Go学习笔记》 // 雨痕的 214 | 《Go语言实战》 // 强烈推荐 215 | // 网上资料 216 | https://github.com/astaxie/build-web-application-with-golang // 谢大的 217 | https://github.com/Unknwon/the-way-to-go_ZH_CN // 无闻 218 | https://github.com/Unknwon/go-fundamental-programming // 无闻教学视频 219 | // 第三方类库 220 | https://golanglibs.com/ 221 | // 大杂烩 222 | https://github.com/avelino/awesome-go 223 | 224 | 225 | 226 | /******************************************************************************* 227 | * References 228 | ******************************************************************************/ 229 | https://github.com/a8m/go-lang-cheat-sheet 230 | https://github.com/LeCoupa/awesome-cheatsheets 231 | -------------------------------------------------------------------------------- /Go/hello-world.go: -------------------------------------------------------------------------------- 1 | /**.----------------------------------------------- 2 | * | Author: guanguans 3 | * '---------------------------------------------*/ 4 | 5 | package main 6 | 7 | import "fmt" 8 | 9 | func main() { 10 | fmt.Println("Hello World") 11 | } 12 | -------------------------------------------------------------------------------- /Linux/Vim.md: -------------------------------------------------------------------------------- 1 | # Vim 2 | 3 | [Vim](http://www.vim.org) 4 | (Vi IMproved) 是 Unix 上的流行编辑器 vi 的克隆版本。这个文本编辑器 5 | 是为性能和提升效率而设计的,并且在大多数基于 unix 的系统上普遍存在。 6 | 它有大量的快捷键可用来快速导航到文件的特定位置,以便进行快速编辑。 7 | 8 | ## Vim 导航基础 9 | 10 | ``` bash 11 | vim # 在 Vim 中打开 12 | :q # 退出 Vim 13 | :w # 保存当前文件 14 | :wq # 保存文件并退出 Vim 15 | :q! # 退出 Vim 并且不保存文件 16 | # ! *强制* 执行 :q, 因此没有保存就退出 Vim 17 | :x # 保存文件并且退出 Vim, 是 :wq 的简写版本 18 | 19 | u # 撤销 20 | CTRL+R # 重做 21 | 22 | h # 左移一个字符 23 | j # 下移一行 24 | k # 上移一行 25 | l # 右移一个字符 26 | 27 | # 在行内移动 28 | 29 | 0 # 移到行首 30 | $ # 移到行尾 31 | ^ # 移到行内的第一个非空白字符处 32 | 33 | # 在文本中查找 34 | 35 | /word # 光标之后的所有该词都高亮显示 36 | ?word # 光标之前的所有该词都高亮显示 37 | n # 查找后将光标移到该词的下一个出现位置 38 | N # 光标移到该词的上一个出现位置 39 | 40 | :%s/foo/bar/g # 将文件每一行上的所有 'foo' 都改成 'bar' 41 | :s/foo/bar/g # 将当前行上的所有 'foo' 都改成 'bar' 42 | 43 | # 跳到字符处 44 | 45 | f<字符> # 向前跳移到 <字符> 上 46 | t<字符> # 向前跳移到 <字符> 的左侧 47 | 48 | # 例如, 49 |    f<               # 向前跳移到 < 上 50 | t< # 向前跳移到 < 的左侧 51 | 52 | # 按词移动 53 | # 默认一个单词由字母,数字和下划线组成 54 | 55 |    w               # 移动到下一个词首 56 |    b               # 移动到前一个词首 57 |    e               # 移动到下一个词尾 58 | 59 | 60 | # 移动的其它命令 61 | 62 | gg # 移到文件顶部 63 | G # 移到文件末尾 64 | :NUM # 移到第 NUM 行 (NUM 是任意数字) 65 | H # 移到屏幕顶部 66 | M # 移到屏幕中间位置 67 | L # 移到屏幕末尾 68 | ``` 69 | 70 | ## 模式 71 | 72 | Vim 基于 **模式** 这个概念。 73 | 74 | 命令模式 - Vim 启动后就处于这个模式,用于导航和操作命令 75 | 插入模式 - 用于在你的文件中进行修改 76 | 可视模式 - 用于高亮文本并对它们进行操作 77 | Ex 模式 - 用于跳到底部的 ':' 提示行上输入命令 78 | 79 | ``` bash 80 | i # 在光标位置前,将 Vim 切换到插入模式 81 | a # 在光标位置后,将 Vim 切换到插入模式 82 | v # 将 Vim 切换到可视模式 83 | : # 将 Vim 切换到 ex 模式 84 | # 无论你当前处于什么模式,都返回到命令模式 85 | 86 | # 复制和粘贴文本 87 | 88 | y # 复制所选的内容 89 | yy # 复制当前行 90 | d # 删除所选的内容 91 | dd # 删除当前行 92 | p # 在当前光标位置后粘贴复制的文本 93 | P # 在当前光标位置前粘贴复制的文本 94 | x # 删除当前光标位置处的字符 95 | ``` 96 | 97 | ## Vim 的 '语法' 98 | 99 | Vim 可以被认为是按 '动词-修饰词-名词' 格式编排的一组命令: 100 | 101 | 动词 - 你的动作 102 | 修饰词 - 你如何执行你的动作 103 | 名词 - 你的动作所作用于的对象 104 | 105 | 关于 '动词','修饰词',和 '名词' 的几个重要例子: 106 | 107 | ``` bash 108 | # '动词' 109 | 110 | d # 删除 111 | c # 修改 112 | y # 复制 113 | v # 可视化选择 114 | 115 | # '修饰词' 116 | 117 | i # 内部的 118 | a # 周围的 119 | NUM # 数字 (NUM 是任意数字) 120 | f # 查找文本并位于其上 121 | t # 查找文本并停于其前面 122 | / # 从光标处开始查找字符串 123 | ? # 在光标前查找字符串 124 | 125 | # '名词' 126 | 127 | w # 词 128 | s # 句子 129 | p # 段落 130 | b # 块 131 | 132 | # 示例 '语句' 或命令 133 | 134 | d2w # 删除 2 个词 135 | cis # 修改段落内的内容 136 | yip # 复制段落内的内容 (复制你所在的段落) 137 | ct< # 修改直到括号开启处 138 | # 对你的当前位置直到下个括号开启处的内容进行修改 139 | d$ # 删除直到行尾 140 | ``` 141 | 142 | ## 一些快捷键和技巧 143 | 144 | ``` bash 145 | > # 将所选内容缩进一级 146 | < # 将所选内容取消缩进一级 147 | :earlier 15m # 将文档还原到 15 分钟前的状态 148 | :later 15m # 逆转上述命令 149 | ddp # 相邻行交换位置,先 dd 再 p 150 | . # 重复之前动作 151 | ``` 152 | 153 | ## 宏 154 | 155 | 宏基本上来说就是可录制的动作。 156 | 当你开始录制宏时,它会记录你使用的 **每个** 动作和命令, 157 | 直到你停止录制。当调用宏时,它会将这个完全相同的动作和命令序列 158 | 再次应用于所选文本之上。 159 | 160 | ``` bash 161 | qa # 开始录制一个叫 'a' 的宏 162 | q # 停止录制 163 | @a # 重播宏 164 | ``` 165 | 166 | ### 配置 ~/.vimrc 167 | 168 | .vimrc 可用于在启动时对 Vim 进行配置。 169 | 170 | 这里是一个示例 ~/.vimrc 文件: 171 | 172 | ``` bash 173 | " 示例 ~/.vimrc 174 | " 2015.10 175 | 176 | " 需要 Vim iMproved 版本 177 | set nocompatible 178 | 179 | " 根据文件名检测文件类型,以便能进行智能自动缩进等操作。 180 | filetype indent plugin on 181 | 182 | " 开启语法高亮 183 | syntax on 184 | 185 | " 更好的命令行补全 186 | set wildmenu 187 | 188 | " 除了当使用大写字母时使用大小写无关查找 189 | set ignorecase 190 | set smartcase 191 | 192 | " 当新开一行时,如果没有开启文件特定的缩进规则, 193 | " 则缩进保持与你当前行一致 194 | set autoindent 195 | 196 | " 在左侧显示行号 197 | set number 198 | 199 | " 缩进选项,根据个人偏好进行修改 200 | 201 | " 每个 TAB 的可视空格数 202 | set tabstop=4 203 | 204 | " 编辑时 TAB 对应的空格数 205 | set softtabstop=4 206 | 207 | " 当使用缩进操作 (>> 和 <<) 时缩进的空格数 208 | set shiftwidth=4 209 | 210 | " 将 TAB 转换成空格 211 | set expandtab 212 | 213 | " 为缩进和对齐开启智能化的 TAB 和空格切换功能 214 | set smarttab 215 | ``` 216 | 217 | ### 参考 218 | 219 | [Vim | Home](http://www.vim.org/index.php) 220 | 221 | `$ vimtutor` 222 | 223 | [A vim Tutorial and Primer](https://danielmiessler.com/study/vim/) 224 | 225 | [What are the dark corners of Vim your mom never told you about? (Stack Overflow thread)](http://stackoverflow.com/questions/726894/what-are-the-dark-corners-of-vim-your-mom-never-told-you-about) 226 | 227 | [Arch Linux Wiki](https://wiki.archlinux.org/index.php/Vim) 228 | -------------------------------------------------------------------------------- /Linux/bash.md: -------------------------------------------------------------------------------- 1 | # Bash 2 | 3 | Bash 是一个为 GNU 计划编写的 Unix shell,是 Linux 和 Mac OS X 下的默认 shell。 4 | 以下大多数例子可以作为脚本的一部分运行,也可直接在 shell 下交互执行。 5 | 6 | [更多信息](http://www.gnu.org/software/bash/manual/bashref.html) 7 | 8 | ```bash 9 | #!/bin/bash 10 | # 脚本的第一行叫 shebang,用来告知系统如何执行该脚本: 11 | # 参见: http://en.wikipedia.org/wiki/Shebang_(Unix) 12 | # 如你所见,注释以 # 开头,shebang 也是注释。 13 | 14 | # 显示 “Hello world!” 15 | echo Hello world! 16 | 17 | # 每一句指令以换行或分号隔开: 18 | echo 'This is the first line'; echo 'This is the second line' 19 | 20 | # 声明一个变量: 21 | Variable="Some string" 22 | 23 | # 下面是错误的做法: 24 | Variable = "Some string" 25 | # Bash 会把 Variable 当做一个指令,由于找不到该指令,因此这里会报错。 26 | 27 | # 也不可以这样: 28 | Variable= 'Some string' 29 | # Bash 会认为 'Some string' 是一条指令,由于找不到该指令,这里再次报错。 30 | # (这个例子中 'Variable=' 这部分会被当作仅对 'Some string' 起作用的赋值。) 31 | 32 | # 使用变量: 33 | echo $Variable 34 | echo "$Variable" 35 | echo '$Variable' 36 | # 当你赋值 (assign) 、导出 (export),或者以其他方式使用变量时,变量名前不加 $。 37 | # 如果要使用变量的值, 则要加 $。 38 | # 注意: ' (单引号) 不会展开变量(即会屏蔽掉变量)。 39 | 40 | 41 | # 在变量内部进行字符串代换 42 | echo ${Variable/Some/A} 43 | # 会把 Variable 中首次出现的 "some" 替换成 “A”。 44 | 45 | # 变量的截取 46 | Length=7 47 | echo ${Variable:0:Length} 48 | # 这样会仅返回变量值的前7个字符 49 | 50 | # 变量的默认值 51 | echo ${Foo:-"DefaultValueIfFooIsMissingOrEmpty"} 52 | # 对 null (Foo=) 和空串 (Foo="") 起作用; 零(Foo=0)时返回0 53 | # 注意这仅返回默认值而不是改变变量的值 54 | 55 | # 内置变量: 56 | # 下面的内置变量很有用 57 | echo "Last program return value: $?" 58 | echo "Script's PID: $$" 59 | echo "Number of arguments: $#" 60 | echo "Scripts arguments: $@" 61 | echo "Scripts arguments separated in different variables: $1 $2..." 62 | 63 | # 读取输入: 64 | echo "What's your name?" 65 | read Name # 这里不需要声明新变量 66 | echo Hello, $Name! 67 | 68 | # 通常的 if 结构看起来像这样: 69 | # 'man test' 可查看更多的信息 70 | if [ $Name -ne $USER ] 71 | then 72 | echo "Your name isn't your username" 73 | else 74 | echo "Your name is your username" 75 | fi 76 | 77 | # 根据上一个指令执行结果决定是否执行下一个指令 78 | echo "Always executed" || echo "Only executed if first command fails" 79 | echo "Always executed" && echo "Only executed if first command does NOT fail" 80 | 81 | # 在 if 语句中使用 && 和 || 需要多对方括号 82 | if [ $Name == "Steve" ] && [ $Age -eq 15 ] 83 | then 84 | echo "This will run if $Name is Steve AND $Age is 15." 85 | fi 86 | 87 | if [ $Name == "Daniya" ] || [ $Name == "Zach" ] 88 | then 89 | echo "This will run if $Name is Daniya OR Zach." 90 | fi 91 | 92 | # 表达式的格式如下: 93 | echo $(( 10 + 5 )) 94 | 95 | # 与其他编程语言不同的是,bash 运行时依赖上下文。比如,使用 ls 时,列出当前目录。 96 | ls 97 | 98 | # 指令可以带有选项: 99 | ls -l # 列出文件和目录的详细信息 100 | 101 | # 前一个指令的输出可以当作后一个指令的输入。grep 用来匹配字符串。 102 | # 用下面的指令列出当前目录下所有的 txt 文件: 103 | ls -l | grep "\.txt" 104 | 105 | # 重定向输入和输出(标准输入,标准输出,标准错误)。 106 | # 以 ^EOF$ 作为结束标记从标准输入读取数据并覆盖 hello.py : 107 | cat > hello.py << EOF 108 | #!/usr/bin/env python 109 | from __future__ import print_function 110 | import sys 111 | print("#stdout", file=sys.stdout) 112 | print("#stderr", file=sys.stderr) 113 | for line in sys.stdin: 114 | print(line, file=sys.stdout) 115 | EOF 116 | 117 | # 重定向可以到输出,输入和错误输出。 118 | python hello.py < "input.in" 119 | python hello.py > "output.out" 120 | python hello.py 2> "error.err" 121 | python hello.py > "output-and-error.log" 2>&1 122 | python hello.py > /dev/null 2>&1 123 | # > 会覆盖已存在的文件, >> 会以累加的方式输出文件中。 124 | python hello.py >> "output.out" 2>> "error.err" 125 | 126 | # 覆盖 output.out , 追加 error.err 并统计行数 127 | info bash 'Basic Shell Features' 'Redirections' > output.out 2>> error.err 128 | wc -l output.out error.err 129 | 130 | # 运行指令并打印文件描述符 (比如 /dev/fd/123) 131 | # 具体可查看: man fd 132 | echo <(echo "#helloworld") 133 | 134 | # 以 "#helloworld" 覆盖 output.out: 135 | cat > output.out <(echo "#helloworld") 136 | echo "#helloworld" > output.out 137 | echo "#helloworld" | cat > output.out 138 | echo "#helloworld" | tee output.out >/dev/null 139 | 140 | # 清理临时文件并显示详情(增加 '-i' 选项启用交互模式) 141 | rm -v output.out error.err output-and-error.log 142 | 143 | # 一个指令可用 $( ) 嵌套在另一个指令内部: 144 | # 以下的指令会打印当前目录下的目录和文件总数 145 | echo "There are $(ls | wc -l) items here." 146 | 147 | # 反引号 `` 起相同作用,但不允许嵌套 148 | # 优先使用 $( ). 149 | echo "There are `ls | wc -l` items here." 150 | 151 | # Bash 的 case 语句与 Java 和 C++ 中的 switch 语句类似: 152 | case "$Variable" in 153 | # 列出需要匹配的字符串 154 | 0) echo "There is a zero.";; 155 | 1) echo "There is a one.";; 156 | *) echo "It is not null.";; 157 | esac 158 | 159 | # 循环遍历给定的参数序列: 160 | # 变量$Variable 的值会被打印 3 次。 161 | for Variable in {1..3} 162 | do 163 | echo "$Variable" 164 | done 165 | 166 | # 或传统的 “for循环” : 167 | for ((a=1; a <= 3; a++)) 168 | do 169 | echo $a 170 | done 171 | 172 | # 也可以用于文件 173 | # 用 cat 输出 file1 和 file2 内容 174 | for Variable in file1 file2 175 | do 176 | cat "$Variable" 177 | done 178 | 179 | # 或作用于其他命令的输出 180 | # 对 ls 输出的文件执行 cat 指令。 181 | for Output in $(ls) 182 | do 183 | cat "$Output" 184 | done 185 | 186 | # while 循环: 187 | while [ true ] 188 | do 189 | echo "loop body here..." 190 | break 191 | done 192 | 193 | # 你也可以使用函数 194 | # 定义函数: 195 | function foo () 196 | { 197 | echo "Arguments work just like script arguments: $@" 198 | echo "And: $1 $2..." 199 | echo "This is a function" 200 | return 0 201 | } 202 | 203 | # 更简单的方法 204 | bar () 205 | { 206 | echo "Another way to declare functions!" 207 | return 0 208 | } 209 | 210 | # 调用函数 211 | foo "My name is" $Name 212 | 213 | # 有很多有用的指令需要学习: 214 | # 打印 file.txt 的最后 10 行 215 | tail -n 10 file.txt 216 | # 打印 file.txt 的前 10 行 217 | head -n 10 file.txt 218 | # 将 file.txt 按行排序 219 | sort file.txt 220 | # 报告或忽略重复的行,用选项 -d 打印重复的行 221 | uniq -d file.txt 222 | # 打印每行中 ',' 之前内容 223 | cut -d ',' -f 1 file.txt 224 | # 将 file.txt 文件所有 'okay' 替换为 'great', (兼容正则表达式) 225 | sed -i 's/okay/great/g' file.txt 226 | # 将 file.txt 中匹配正则的行打印到标准输出 227 | # 这里打印以 "foo" 开头, "bar" 结尾的行 228 | grep "^foo.*bar$" file.txt 229 | # 使用选项 "-c" 统计行数 230 | grep -c "^foo.*bar$" file.txt 231 | # 如果只是要按字面形式搜索字符串而不是按正则表达式,使用 fgrep (或 grep -F) 232 | fgrep "^foo.*bar$" file.txt 233 | 234 | 235 | # 以 bash 内建的 'help' 指令阅读 Bash 自带文档: 236 | help 237 | help help 238 | help for 239 | help return 240 | help source 241 | help . 242 | 243 | # 用 man 指令阅读相关的 Bash 手册 244 | apropos bash 245 | man 1 bash 246 | man bash 247 | 248 | # 用 info 指令查阅命令的 info 文档 (info 中按 ? 显示帮助信息) 249 | apropos info | grep '^info.*(' 250 | man info 251 | info info 252 | info 5 info 253 | 254 | # 阅读 Bash 的 info 文档: 255 | info bash 256 | info bash 'Bash Features' 257 | info bash 6 258 | info --apropos bash 259 | ``` 260 | -------------------------------------------------------------------------------- /Lua/Lua.md: -------------------------------------------------------------------------------- 1 | # Lua 2 | 3 | ```lua 4 | -- 单行注释以两个连字符开头 5 | 6 | --[[ 7 | 多行注释 8 | --]] 9 | 10 | ---------------------------------------------------- 11 | -- 1. 变量和流程控制 12 | ---------------------------------------------------- 13 | 14 | num = 42 -- 所有的数字都是双精度浮点型。 15 | -- 别害怕,64位的双精度浮点型数字中有52位用于 16 | -- 保存精确的整型值; 对于52位以内的整型值, 17 | -- 不用担心精度问题。 18 | 19 | s = 'walternate' -- 和Python一样,字符串不可变。 20 | t = "也可以用双引号" 21 | u = [[ 多行的字符串 22 | 以两个方括号 23 | 开始和结尾。]] 24 | t = nil -- 撤销t的定义; Lua 支持垃圾回收。 25 | 26 | -- 块使用do/end之类的关键字标识: 27 | while num < 50 do 28 | num = num + 1 -- 不支持 ++ 或 += 运算符。 29 | end 30 | 31 | -- If语句: 32 | if num > 40 then 33 | print('over 40') 34 | elseif s ~= 'walternate' then -- ~= 表示不等于。 35 | -- 像Python一样,用 == 检查是否相等 ;字符串同样适用。 36 | io.write('not over 40\n') -- 默认标准输出。 37 | else 38 | -- 默认全局变量。 39 | thisIsGlobal = 5 -- 通常使用驼峰。 40 | 41 | -- 如何定义局部变量: 42 | local line = io.read() -- 读取标准输入的下一行。 43 | 44 | -- ..操作符用于连接字符串: 45 | print('Winter is coming, ' .. line) 46 | end 47 | 48 | -- 未定义的变量返回nil。 49 | -- 这不是错误: 50 | foo = anUnknownVariable -- 现在 foo = nil. 51 | 52 | aBoolValue = false 53 | 54 | --只有nil和false为假; 0和 ''均为真! 55 | if not aBoolValue then print('false') end 56 | 57 | -- 'or'和 'and'短路 58 | -- 类似于C/js里的 a?b:c 操作符: 59 | ans = aBoolValue and 'yes' or 'no' --> 'no' 60 | 61 | karlSum = 0 62 | for i = 1, 100 do -- 范围包含两端 63 | karlSum = karlSum + i 64 | end 65 | 66 | -- 使用 "100, 1, -1" 表示递减的范围: 67 | fredSum = 0 68 | for j = 100, 1, -1 do fredSum = fredSum + j end 69 | 70 | -- 通常,范围表达式为begin, end[, step]. 71 | 72 | -- 循环的另一种结构: 73 | repeat 74 | print('the way of the future') 75 | num = num - 1 76 | until num == 0 77 | 78 | ---------------------------------------------------- 79 | -- 2. 函数。 80 | ---------------------------------------------------- 81 | 82 | function fib(n) 83 | if n < 2 then return n end 84 | return fib(n - 2) + fib(n - 1) 85 | end 86 | 87 | -- 支持闭包及匿名函数: 88 | function adder(x) 89 | -- 调用adder时,会创建返回的函数, 90 | -- 并且会记住x的值: 91 | return function (y) return x + y end 92 | end 93 | a1 = adder(9) 94 | a2 = adder(36) 95 | print(a1(16)) --> 25 96 | print(a2(64)) --> 100 97 | 98 | -- 返回值、函数调用和赋值都可以 99 | -- 使用长度不匹配的list。 100 | -- 不匹配的接收方会被赋值nil; 101 | -- 不匹配的发送方会被丢弃。 102 | 103 | x, y, z = 1, 2, 3, 4 104 | -- x = 1、y = 2、z = 3, 而 4 会被丢弃。 105 | 106 | function bar(a, b, c) 107 | print(a, b, c) 108 | return 4, 8, 15, 16, 23, 42 109 | end 110 | 111 | x, y = bar('zaphod') --> 打印 "zaphod nil nil" 112 | -- 现在 x = 4, y = 8, 而值15..42被丢弃。 113 | 114 | -- 函数是一等公民,可以是局部的,也可以是全局的。 115 | -- 以下表达式等价: 116 | function f(x) return x * x end 117 | f = function (x) return x * x end 118 | 119 | -- 这些也是等价的: 120 | local function g(x) return math.sin(x) end 121 | local g; g = function (x) return math.sin(x) end 122 | -- 以上均因'local g',使得g可以自引用。 123 | local g = function(x) return math.sin(x) end 124 | -- 等价于 local function g(x)..., 但函数体中g不可自引用 125 | 126 | -- 顺便提下,三角函数以弧度为单位。 127 | 128 | -- 用一个字符串参数调用函数,可以省略括号: 129 | print 'hello' --可以工作。 130 | 131 | -- 调用函数时,如果只有一个table参数, 132 | -- 同样可以省略括号(table详情见下): 133 | print {} -- 一样可以工作。 134 | 135 | ---------------------------------------------------- 136 | -- 3. Table。 137 | ---------------------------------------------------- 138 | 139 | -- Table = Lua唯一的组合数据结构; 140 | -- 它们是关联数组。 141 | -- 类似于PHP的数组或者js的对象, 142 | -- 它们是哈希表或者字典,也可以当列表使用。 143 | 144 | -- 按字典/map的方式使用Table: 145 | 146 | -- Dict字面量默认使用字符串类型的key: 147 | t = {key1 = 'value1', key2 = false} 148 | 149 | -- 字符串key可以使用类似js的点标记: 150 | print(t.key1) -- 打印 'value1'. 151 | t.newKey = {} -- 添加新的键值对。 152 | t.key2 = nil -- 从table删除 key2。 153 | 154 | -- 使用任何非nil的值作为key: 155 | u = {['@!#'] = 'qbert', [{}] = 1729, [6.28] = 'tau'} 156 | print(u[6.28]) -- 打印 "tau" 157 | 158 | -- 数字和字符串的key按值匹配的 159 | -- table按id匹配。 160 | a = u['@!#'] -- 现在 a = 'qbert'. 161 | b = u[{}] -- 我们或许期待的是 1729, 但是得到的是nil: 162 | -- b = nil ,因为没有找到。 163 | -- 之所以没找到,是因为我们用的key与保存数据时用的不是同 164 | -- 一个对象。 165 | -- 所以字符串和数字是移植性更好的key。 166 | 167 | -- 只需要一个table参数的函数调用不需要括号: 168 | function h(x) print(x.key1) end 169 | h{key1 = 'Sonmi~451'} -- 打印'Sonmi~451'. 170 | 171 | for key, val in pairs(u) do -- 遍历Table 172 | print(key, val) 173 | end 174 | 175 | -- _G 是一个特殊的table,用于保存所有的全局变量 176 | print(_G['_G'] == _G) -- 打印'true'. 177 | 178 | -- 按列表/数组的方式使用: 179 | 180 | -- 列表字面量隐式添加整数键: 181 | v = {'value1', 'value2', 1.21, 'gigawatts'} 182 | for i = 1, #v do -- #v 是列表的大小 183 | print(v[i]) -- 索引从 1 开始!! 太疯狂了! 184 | end 185 | -- 'list'并非真正的类型,v 其实是一个table, 186 | -- 只不过它用连续的整数作为key,可以像list那样去使用。 187 | 188 | ---------------------------------------------------- 189 | -- 3.1 元表(metatable) 和元方法(metamethod)。 190 | ---------------------------------------------------- 191 | 192 | -- table的元表提供了一种机制,支持类似操作符重载的行为。 193 | -- 稍后我们会看到元表如何支持类似js prototype的行为。 194 | 195 | f1 = {a = 1, b = 2} -- 表示一个分数 a/b. 196 | f2 = {a = 2, b = 3} 197 | 198 | -- 这会失败: 199 | -- s = f1 + f2 200 | 201 | metafraction = {} 202 | function metafraction.__add(f1, f2) 203 | local sum = {} 204 | sum.b = f1.b * f2.b 205 | sum.a = f1.a * f2.b + f2.a * f1.b 206 | return sum 207 | end 208 | 209 | setmetatable(f1, metafraction) 210 | setmetatable(f2, metafraction) 211 | 212 | s = f1 + f2 -- 调用在f1的元表上的__add(f1, f2) 方法 213 | 214 | -- f1, f2 没有关于元表的key,这点和js的prototype不一样。 215 | -- 因此你必须用getmetatable(f1)获取元表。 216 | -- 元表是一个普通的table, 217 | -- 元表的key是普通的Lua中的key,例如__add。 218 | 219 | -- 但是下面一行代码会失败,因为s没有元表: 220 | -- t = s + s 221 | -- 下面提供的与类相似的模式可以解决这个问题: 222 | 223 | -- 元表的__index 可以重载用于查找的点操作符: 224 | defaultFavs = {animal = 'gru', food = 'donuts'} 225 | myFavs = {food = 'pizza'} 226 | setmetatable(myFavs, {__index = defaultFavs}) 227 | eatenBy = myFavs.animal -- 可以工作!感谢元表 228 | 229 | -- 如果在table中直接查找key失败,会使用 230 | -- 元表的__index 递归地重试。 231 | 232 | -- __index的值也可以是function(tbl, key) 233 | -- 这样可以支持自定义查找。 234 | 235 | -- __index、__add等的值,被称为元方法。 236 | -- 这里是一个table元方法的清单: 237 | 238 | -- __add(a, b) for a + b 239 | -- __sub(a, b) for a - b 240 | -- __mul(a, b) for a * b 241 | -- __div(a, b) for a / b 242 | -- __mod(a, b) for a % b 243 | -- __pow(a, b) for a ^ b 244 | -- __unm(a) for -a 245 | -- __concat(a, b) for a .. b 246 | -- __len(a) for #a 247 | -- __eq(a, b) for a == b 248 | -- __lt(a, b) for a < b 249 | -- __le(a, b) for a <= b 250 | -- __index(a, b) for a.b 251 | -- __newindex(a, b, c) for a.b = c 252 | -- __call(a, ...) for a(...) 253 | 254 | ---------------------------------------------------- 255 | -- 3.2 与类相似的table和继承。 256 | ---------------------------------------------------- 257 | 258 | -- Lua没有内建的类;可以通过不同的方法,利用表和元表 259 | -- 来实现类。 260 | 261 | -- 下面是一个例子,解释在后面: 262 | 263 | Dog = {} -- 1. 264 | 265 | function Dog:new() -- 2. 266 | local newObj = {sound = 'woof'} -- 3. 267 | self.__index = self -- 4. 268 | return setmetatable(newObj, self) -- 5. 269 | end 270 | 271 | function Dog:makeSound() -- 6. 272 | print('I say ' .. self.sound) 273 | end 274 | 275 | mrDog = Dog:new() -- 7. 276 | mrDog:makeSound() -- 'I say woof' -- 8. 277 | 278 | -- 1. Dog看上去像一个类;其实它是一个table。 279 | -- 2. 函数tablename:fn(...) 等价于 280 | -- 函数tablename.fn(self, ...) 281 | -- 冒号(:)只是添加了self作为第一个参数。 282 | -- 阅读7 & 8条 了解self变量是如何得到其值的。 283 | -- 3. newObj是类Dog的一个实例。 284 | -- 4. self = 被继承的类。通常self = Dog,不过继承可以改变它。 285 | -- 如果把newObj的元表和__index都设置为self, 286 | -- newObj就可以得到self的函数。 287 | -- 5. 备忘:setmetatable返回其第一个参数。 288 | -- 6. 冒号(:)的作用和第2条一样,不过这里 289 | -- self是一个实例,而不是类 290 | -- 7. 等价于Dog.new(Dog),所以在new()中,self = Dog。 291 | -- 8. 等价于mrDog.makeSound(mrDog); self = mrDog。 292 | 293 | ---------------------------------------------------- 294 | 295 | -- 继承的例子: 296 | 297 | LoudDog = Dog:new() -- 1. 298 | 299 | function LoudDog:makeSound() 300 | local s = self.sound .. ' ' -- 2. 301 | print(s .. s .. s) 302 | end 303 | 304 | seymour = LoudDog:new() -- 3. 305 | seymour:makeSound() -- 'woof woof woof' -- 4. 306 | 307 | -- 1. LoudDog获得Dog的方法和变量列表。 308 | -- 2. 因为new()的缘故,self拥有了一个'sound' key,参见第3条。 309 | -- 3. 等价于LoudDog.new(LoudDog),转换一下就是 310 | -- Dog.new(LoudDog),这是因为LoudDog没有'new' key, 311 | -- 但是它的元表中有 __index = Dog。 312 | -- 结果: seymour的元表是LoudDog,并且 313 | -- LoudDog.__index = Dog。所以有seymour.key 314 | -- = seymour.key, LoudDog.key, Dog.key 315 | -- 从其中第一个有指定key的table获取。 316 | -- 4. 在LoudDog可以找到'makeSound'的key; 317 | -- 等价于LoudDog.makeSound(seymour)。 318 | 319 | -- 如果有必要,子类也可以有new(),与基类相似: 320 | function LoudDog:new() 321 | local newObj = {} 322 | -- 初始化newObj 323 | self.__index = self 324 | return setmetatable(newObj, self) 325 | end 326 | 327 | ---------------------------------------------------- 328 | -- 4. 模块 329 | ---------------------------------------------------- 330 | 331 | 332 | --[[ 我把这部分给注释了,这样脚本剩下的部分可以运行 333 | ``` 334 | 335 | ```lua 336 | -- 假设文件mod.lua的内容类似这样: 337 | local M = {} 338 | 339 | local function sayMyName() 340 | print('Hrunkner') 341 | end 342 | 343 | function M.sayHello() 344 | print('Why hello there') 345 | sayMyName() 346 | end 347 | 348 | return M 349 | 350 | -- 另一个文件可以使用mod.lua的功能: 351 | local mod = require('mod') -- 运行文件mod.lua. 352 | 353 | -- require是包含模块的标准做法。 354 | -- require等价于: (针对没有被缓存的情况;参见后面的内容) 355 | local mod = (function () 356 | 357 | end)() 358 | -- mod.lua被包在一个函数体中,因此mod.lua的局部变量 359 | -- 对外不可见。 360 | 361 | -- 下面的代码可以工作,因为在这里mod = mod.lua 中的 M: 362 | mod.sayHello() -- Says hello to Hrunkner. 363 | 364 | -- 这是错误的;sayMyName只在mod.lua中存在: 365 | mod.sayMyName() -- 错误 366 | 367 | -- require返回的值会被缓存,所以一个文件只会被运行一次, 368 | -- 即使它被require了多次。 369 | 370 | -- 假设mod2.lua包含代码"print('Hi!')"。 371 | local a = require('mod2') -- 打印Hi! 372 | local b = require('mod2') -- 不再打印; a=b. 373 | 374 | -- dofile与require类似,但是不缓存: 375 | dofile('mod2') --> Hi! 376 | dofile('mod2') --> Hi! (再次运行,与require不同) 377 | 378 | -- loadfile加载一个lua文件,但是并不运行它。 379 | f = loadfile('mod2') -- Calling f() runs mod2.lua. 380 | 381 | -- loadstring是loadfile的字符串版本。 382 | g = loadstring('print(343)') --返回一个函数。 383 | g() -- 打印343; 在此之前什么也不打印。 384 | 385 | --]] 386 | ``` 387 | 388 | ## 参考 389 | 390 | 391 | 392 | 为什么?我非常兴奋地学习 lua, 这样我就可以使用[Löve 2D 游戏引擎](http://love2d.org/)来编游戏。 393 | 394 | 怎么做?我从[BlackBulletIV 的面向程序员的 Lua 指南](http://nova-fusion.com/2012/08/27/lua-for-programmers-part-1/)入门。接着我阅读了官方的[Lua 编程](http://www.lua.org/pil/contents.html)一书。 395 | 396 | lua-users.org 上的[Lua 简明参考](http://lua-users.org/files/wiki_insecure/users/thomasl/luarefv51.pdf)应该值得一看。 397 | 398 | 本文没有涉及标准库的内容: 399 | 400 | * string library 401 | * table library 402 | * math library 403 | * io library 404 | * os library 405 | 406 | 顺便说一下,整个文件是可运行的 Lua; 407 | 保存为 learn-cn.lua 用命令 `lua learn-cn.lua` 启动吧! 408 | 409 | 本文首次撰写于 [tylerneylon.com](http://tylerneylon.com) 同时也有 [github gist](https://gist.github.com/tylerneylon/5853042) 版. 410 | 411 | 使用 Lua,欢乐常在! 412 | -------------------------------------------------------------------------------- /MongoDB/SQL到Mongo的对应表.md: -------------------------------------------------------------------------------- 1 | # SQL 到 Mongo 的对应表 2 | 3 | 这个列表是 PHP 版本的 [» SQL to Mongo](http://www.mongoing.com/docs/reference/sql-comparison.html) 对应表(在 MongoDB 官方手册中有更加通用的版本)。 4 | 5 | | SQL 查询语句 | Mongo 查询语句 | 6 | | --- | --- | 7 | |CREATE TABLE USERS (a Number, b Number) | 隐式的创建,或 [MongoDB::createCollection()](mongodb.createcollection.php). | 8 | |INSERT INTO USERS VALUES(1,1) |$db->users->insert(array("a" => 1, "b" => 1)); | 9 | |SELECT a,b FROM users |$db->users->find(array(), array("a" => 1, "b" => 1)); | 10 | |SELECT * FROM users WHERE age=33 |$db->users->find(array("age" => 33)); | 11 | |SELECT a,b FROM users WHERE age=33 |$db->users->find(array("age" => 33), array("a" => 1, "b" => 1)); | 12 | |SELECT a,b FROM users WHERE age=33 ORDER BY name |$db->users->find(array("age" => 33), array("a" => 1, "b" => 1))->sort(array("name" => 1)); | 13 | |SELECT * FROM users WHERE age>33 |$db->users->find(array("age" => array('$gt' => 33))); | 14 | |SELECT * FROM users WHERE age<33 |$db->users->find(array("age" => array('$lt' => 33))); | 15 | |SELECT * FROM users WHERE name LIKE "%Joe%" |$db->users->find(array("name" => new MongoRegex("/Joe/"))); | 16 | |SELECT * FROM users WHERE name LIKE "Joe%" |$db->users->find(array("name" => new MongoRegex("/^Joe/"))); | 17 | |SELECT * FROM users WHERE age>33 AND age<=40 |$db->users->find(array("age" => array('$gt' => 33, '$lte' => 40))); | 18 | |SELECT * FROM users ORDER BY name DESC |$db->users->find()->sort(array("name" => -1)); | 19 | |CREATE INDEX myindexname ON users(name) |$db->users->ensureIndex(array("name" => 1)); | 20 | |CREATE INDEX myindexname ON users(name,ts DESC) |$db->users->ensureIndex(array("name" => 1, "ts" => -1)); | 21 | |SELECT * FROM users WHERE a=1 and b='q' |$db->users->find(array("a" => 1, "b" => "q")); | 22 | |SELECT * FROM users LIMIT 20, 10 |$db->users->find()->limit(10)->skip(20); | 23 | |SELECT * FROM users WHERE a=1 or b=2 |$db->users->find(array('$or' => array(array("a" => 1), array("b" => 2)))); | 24 | |SELECT * FROM users LIMIT 1 |$db->users->find()->limit(1); | 25 | |EXPLAIN SELECT * FROM users WHERE z=3 |$db->users->find(array("z" => 3))->explain() | 26 | |SELECT DISTINCT last_name FROM users |$db->command(array("distinct" => "users", "key" => "last_name")); | 27 | |SELECT COUNT(*y) FROM users |$db->users->count(); | 28 | |SELECT COUNT(*y) FROM users where AGE > 30 |$db->users->find(array("age" => array('$gt' => 30)))->count(); | 29 | |SELECT COUNT(AGE) from users |$db->users->find(array("age" => array('$exists' => true)))->count(); | 30 | |UPDATE users SET a=1 WHERE b='q' |$db->users->update(array("b" => "q"), array('$set' => array("a" => 1))); | 31 | |UPDATE users SET a=a+2 WHERE b='q' |$db->users->update(array("b" => "q"), array('$inc' => array("a" => 2))); | 32 | |DELETE FROM users WHERE z="abc" |$db->users->remove(array("z" => "abc")); | 33 | 34 | 35 | ## 内嵌、引用选择 36 | 37 | | 更适合内嵌 | 更适合引用 | 38 | | --- | --- | 39 | | 子文档较小 | 子文档较大 | 40 | | 数据不会定期改变 | 数据经常改变 | 41 | | 最终数据一致即可 | 中间阶段的数据必须一致 | 42 | | 文档数据小幅增加 | 文档数据大幅增加 | 43 | | 数据通常需要执行二次查询才能获得 | 数据通常不包含在结果中 | 44 | | 快速读取 | 快速写入 | 45 | -------------------------------------------------------------------------------- /MySQL/MySQL常用函数汇总.md: -------------------------------------------------------------------------------- 1 | # MySQL 常用函数汇总 2 | 3 | 字符串函数 4 | ===== 5 | 6 | | 函数 | 功能 | 7 | | --- | --- | 8 | | CONCAT(s1,s2,……) | 字符串连接 | 9 | | INSERT(str,x,y,instr) | 将指定开始标记到结束的字符串替换为指定字符串 | 10 | | LOWER(str) | 将字符串所有字符转为小写 | 11 | | UPPER(str) | 将字符串所有字符串转为大写 | 12 | | LEFT(str,x) | 返回字符串 str 最左边的 x 个字符 | 13 | | RIGHT(str,x) | 返回字符串 str 最右边的 x 个字符 | 14 | | LPAD(str,n,pad) | 在 str 最左边填充 n 个 pad | 15 | | RPAD(str,n,pad) | 在 str 最右边填充 n 个 pad | 16 | | LTRIM(str) | 去掉字符串 str 左侧的空格 | 17 | | RTRIM(str) | 去掉字符串 str 右侧的空格 | 18 | | REPEAT(str,x) | 返回 str 重复 x 次的结果 | 19 | | STRCMP(s1,s2) | 比较字符串 s1 和 s2 | 20 | | REPLACE(str,a,b) | 用字符串 b 替换字符串 str 中所有出现的字符串 a | 21 | | TRIM(str) | 去掉字符串行尾和行头的空格 | 22 | | SUBSTRING(str,x,y) | 返回从字符串 str x 位置起 y 个字符长度的字串 | 23 | 24 | 数学函数 25 | ==== 26 | 27 | | 函数 | 功能 | 28 | | --- | --- | 29 | | ABS(x) | 返回 x 的绝对值 | 30 | | CEIL(x) | 返回大于 x 的最小整数值 | 31 | | FLOOR(x) | 返回小于 x 的最大整数值 | 32 | | MOD(x,y) | 返回 x/y 的模 | 33 | | RAND() | 返回 0~1 内的随机值 | 34 | | ROUND(x,y) | 返回参数 x 的四舍五入的有 y 位小数的值 | 35 | | TRUNCATE(x,y) | 返回数字 x 截断位 y 位小数的结果 | 36 | 37 | 日期和时间函数 38 | ======= 39 | 40 | | 函数 | 功能 | 41 | | --- | --- | 42 | | CURDATE() | 返回当前日期 | 43 | | CURTIME() | 返回当前时间 | 44 | | NOW() | 返回当前的日期和时间 | 45 | | UNIX_TIMESTAMP(date) | 返回日期 date 的 UNIX 时间戳 | 46 | | FROM_UNIXTIME | 返回 UNIX 时间戳的日期值 | 47 | | WEEK(date) | 返回日期 date 为一年中的第几周 | 48 | | YEAR(date) | 返回日期 date 的年份 | 49 | | HOUR(time) | 返回 time 的小时值 | 50 | | MINUTE(time) | 返回 time 的分钟值 | 51 | | MONTHNAME(date) | 返回 date 的月份名 | 52 | | DATE_FORMAT(date,fmt) | 返回按字符串 fmt 格式日期 date 值 | 53 | | DATE_ADD(date,interval expr type) | 返回一个日期或时间值加上一个时间间隔的时间值 | 54 | | DATEDIFF(expr,expr2) | 返回起始时间 expr 和结束时间 expr2 之间的天数 | 55 | 56 | 流程函数 57 | ==== 58 | 59 | | 函数 | 功能 | 60 | | --- | --- | 61 | | IF(value,t f) | 如果 value 是真,返回 t;否则返回 f | 62 | | IFNULL(value1,value2) | 如果 value1 不为空,返回 value1,否则返回 value2 | 63 | | CASE WHEN [value1] THEN[result1]...ELSE[default]END | 如果 value1 是真,返回 result1,否则返回 result | 64 | | CASE[expr] WHEN [value1]THEN[result1]...ELSE[default]END | 如果 expr 等于 value1,返回 result1,否则返回 default | 65 | 66 | 其他常用函数 67 | ====== 68 | 69 | | 函数 | 功能 | 70 | | --- | --- | 71 | | DATEBASE() | 返回当前数据库名 | 72 | | VERSION() | 返回当前数据库版本 | 73 | | USER() | 返回当前登录用户名 | 74 | | INET_ATON(ip) | 返回 ip 地址的数字表示 | 75 | | INET_NTOA(num) | 返回数字代表的 ip 地址 | 76 | | PASSWORD(str) | 返回字符串 str 的加密版本 | 77 | | MD5() | 返回字符串 str 的 md5 值 | 78 | -------------------------------------------------------------------------------- /MySQL/数据类型.md: -------------------------------------------------------------------------------- 1 | # MySQL 数据类型 2 | 3 | ## 串数据类型 4 | 5 | |数据类型 |说明| 6 | |:---------|:--| 7 | |CHAR |1~255 个字符的定长串。它的长度必须在创建时指定,否则 MySQL 假定为 CHAR(1)| 8 | |ENUM |接受最多 64 K 个串组成的一个预定义集合的某个串| 9 | |LONGTEXT |与 TEXT 相同,但最大长度为 4GB| 10 | |MEDIUMTEXT|与 TEXT 相同,但最大长度为 16K| 11 | |SET |接受最多 64 个串组成的一个预定义集合的零个或多个串| 12 | |TEXT |最大长度为 64K 的变长文本| 13 | |TINYTEXT |与 TEXT 相同,但最大长度为 255 字节| 14 | |VARCHAR |长度可变,最多不超过 255 字节。如果在创建时指定为 VARCHAR(n),则可存储 0 到 n 个字符的变长串(其中 n≤255)| 15 | 16 | ## 数值数据类型 17 | 18 | |数据类型 |说明| 19 | |:---------------|:---| 20 | |BIT |位字段,1~64 位。(在 MySQL 5 之前,BIT 在功能上等价于 TINYINT| 21 | |BIGINT |整数值,支持9223372036854775808~9223372036854775807(如果是 UNSIGNED,为 0~18446744073709551615)的数| 22 | |BOOLEAN(或 BOOL)|布尔标志,或者为 0 或者为 1,主要用于开/关(on/off)标志| 23 | |DECIMAL(或 DEC) |精度可变的浮点值| 24 | |DOUBLE |双精度浮点值| 25 | |FLOAT |单精度浮点值| 26 | |INT(或 INTEGER)|整数值,支持2147483648~2147483647(如果是 UNSIGNED,为 0~4294967295)的数| 27 | |MEDIUMINT |整数值,支持8388608~8388607(如果是 UNSIGNED,为 0~16777215)的数| 28 | |REAL|4 字节的浮点值| 29 | |SMALLINT |整数值,支持32768~32767(如果是 UNSIGNED,为 0~65535)的数| 30 | |TINYINT |整数值,支持128~127(如果为 UNSIGNED,为 0~255)的数| 31 | 32 | ## 日期和时间数据类型 33 | 34 | |数据类型 |说明| 35 | |:--------|:---| 36 | |DATE |表示 1000-01-01~9999-12-31 的日期,格式为 YYYY-MM-DD| 37 | |DATETIME |DATE 和 TIME 的组合| 38 | |TIMESTAMP|功能和 DATETIME 相同(但范围较小)| 39 | |TIME |格式为 HH:MM:SS| 40 | |YEAR |用 2 位数字表示,范围是 70(1970 年)~69(2069 年),用 4 位数字表示,范围是 1901 年~2155 年| 41 | 42 | ## 二进制数据类型 43 | 44 | |数据类型 |说明| 45 | |:---------|:---| 46 | |BLOB |Blob 最大长度为 64KB| 47 | |MEDIUMBLOB|Blob 最大长度为 16MB| 48 | |LONGBLOB |Blob 最大长度为 4GB| 49 | |TINYBLOB |Blob 最大长度为 255 字节| -------------------------------------------------------------------------------- /MySQL/语法.md: -------------------------------------------------------------------------------- 1 | # MySQL 语法 2 | 3 | ## 在阅读语句语法时,应该记住以下约定 4 | 5 | * | 符号用来指出几个选择中的一个,因此, NULL|NOT NULL 表示或者给出 NULL 或者给出 NOT NULL 。 6 | * 包含在方括号中的关键字或子句(如[like this])是可选的。 7 | * 既没有列出所有的 MySQL 语句,也没有列出每一条子句和选项。 8 | 9 | ## SQL 执行顺序 10 | 11 | ``` sql 12 | (8)SELECT (9)DISTINCT (11) 24 | 25 |
26 | 27 | 28 | 29 |
30 |
31 |
32 |
33 |
34 | 列表 35 |
36 |
37 |
38 | {{ ci.rhythmic }} 39 |
40 |
41 | 作者:{{ ci.author }} 42 |
43 |
44 |

45 | {{ ci.paragraphs }} 46 |

47 |
48 |
49 | 50 | 51 |
52 |
53 |
54 |
55 |
56 |
57 | 58 | 61 | 62 | 63 | 64 | 65 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /Vue/vue-base-demo/images/icon_fada.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanguans/notes/28f78aee232e7430425055b795de2d52242eef27/Vue/vue-base-demo/images/icon_fada.png -------------------------------------------------------------------------------- /Vue/vue-base-demo/list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 新闻列表 8 | 9 | 10 | 11 | 12 | 13 |
14 | 29 |
30 |
31 |
32 |
33 |
34 | 列表 35 |
36 |
37 |
    38 |
  • 39 |
    40 | {{ item.author }} 41 |
    42 |
    43 | 46 |
    47 | 50 |
    51 |
    52 |
  • 53 | 54 |
55 |
56 |
57 | 71 |
72 |
73 |
74 |
75 |
76 | 79 |
80 | 81 | 82 | 83 | 84 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /iOS.md: -------------------------------------------------------------------------------- 1 | # iOS 2 | 3 | ## [使我的 iOS 体验更加惊人的应用程序和工具列表](https://github.com/nikitavoloboev/my-ios) 4 | -------------------------------------------------------------------------------- /iOS/app.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanguans/notes/28f78aee232e7430425055b795de2d52242eef27/iOS/app.sqlite -------------------------------------------------------------------------------- /mac-man-cn.md: -------------------------------------------------------------------------------- 1 | # Mac 安装中文版 man 帮助命令 2 | 3 | ![](./Docs/Images/man-cn.png) 4 | 5 | ## [linux 环境安装](https://github.com/man-pages-zh/manpages-zh/blob/master/README.md) 6 | 7 | ## macOS 环境安装 8 | 9 | ### 编译工具安装 10 | 11 | 因为需要编译安装,所以你电脑上需要有编译工具,运行下面两个命令安装 12 | 13 | ``` bash 14 | $ brew install automake 15 | $ brew install opencc 16 | ``` 17 | 18 | ### 安装 19 | 20 | ``` bash 21 | # 进入下载目录 22 | $ cd ~/Downloads/ 23 | # 下载最新版本的源码包 24 | $ wget https://github.com/man-pages-zh/manpages-zh/archive/v1.6.3.3.tar.gz 25 | # 解压源码包(atool命令,推荐安装这个工具,统一所有压缩文档的命令) 26 | $ atool -x v1.6.3.3.tar.gz 27 | # 或者使用这个命令解压 28 | $ tar zxvf v1.6.3.3.tar.gz 29 | # 进入源码包文件夹 30 | $ cd manpages-zh-1.6.3.3/ 31 | # 编译安装 1 32 | $ autoreconf --install --force 33 | # 编译安装 2 34 | $ ./configure 35 | # 编译安装 3 36 | $ sudo make 37 | # 编译安装 4 38 | $ sudo make install 39 | # 配置别名(如果是 zsh 对应处理即可) 40 | $ echo "alias cman='man -M /usr/local/share/man/zh_CN'" >> ~/.bash_profile 41 | # 使别名生效 42 | $ source ~/.bash_profile 43 | # 我们就安装上了中文版本的 man 工具了,但是运行命令会发现乱码。 44 | cman ls 45 | ``` 46 | 47 | ### 安装 groff 新版本解决中文乱码的问题 48 | 49 | ``` bash 50 | # 进入下载目录 51 | $ cd ~/Downloads/ 52 | # 下载1.22版本的源码包 53 | $ wget http://git.savannah.gnu.org/cgit/groff.git/snapshot/groff-1.22.tar.gz 54 | # 解压 55 | $ atool -x groff-1.22.tar.gz 56 | # 进入目录 57 | $ cd groff-1.22 58 | # 编译安装 59 | $ ./configure 60 | $ sudo make 61 | $ sudo make install 62 | # 打开配置文件 63 | $ sudo vim /etc/man.conf 64 | # 进入编辑器之后,在文件末尾添加 65 | `NROFF preconv -e UTF8 | /usr/local/bin/nroff -Tutf8 -mandoc -c` 66 | # 保存退出 67 | # 运行命令,完美解决乱码问题 68 | cman ls 69 | ``` 70 | -------------------------------------------------------------------------------- /macOS.md: -------------------------------------------------------------------------------- 1 | # macOS 2 | 3 | ## [使我的 macOS 体验更加惊人的应用程序和工具列表](https://github.com/nikitavoloboev/my-mac-os) 4 | 5 | ## [在 macOS 上安装开发环境](https://github.com/sb2nov/mac-setup) 6 | 7 | ## [我的 macOS 配置文件](https://github.com/nikitavoloboev/dotfiles) 8 | 9 | ## 命令行增强 10 | 11 | 过去这些年我的命令行本领在逐步加强,我经常会去搜寻工作中能用的更好的命令行工具。下面就是我现在使用的用于增强原有命令行工具的列表。 12 | 13 | ### 怎么忽略我所做的命令行增强 14 | 15 | 通常情况下我会用别名将新的增强的命令行工具覆盖原来的命令(如 `cat` 和 `ping`)。 16 | 17 | 如果我需要运行原来的命令的话(有时我确实需要这么做),我会像下面这样来运行未加修改的原始命令。(我用的是 Mac,你的用法可能不一样) 18 | 19 | ``` bash 20 | $ \cat # 忽略叫 "cat" 的别名 - 具体解释: https://stackoverflow.com/a/16506263/22617 21 | $ command cat # 忽略函数和别名 22 | ``` 23 | 24 | ### bat > cat 25 | 26 | `cat` 用于打印文件的内容,如果你平时用命令行很多的话,例如语法高亮之类的功能会非常有用。我首先发现了 [ccat](https://github.com/jingweno/ccat)[1] 这个有语法高亮功能的工具,然后我发现了 [bat](https://github.com/sharkdp/bat)[2],它的功能有语法高亮、分页、行号和 git 集成。 27 | 28 | `bat` 命令也能让我在(多于一屏的)输出里使用 `/` 搜索(和用 `less` 搜索功能一样)。 29 | 30 | ![](https://dn-linuxcn.qbox.me/data/attachment/album/201810/29/204653xppy14y8y4zu6h7s.gif) 31 | 32 | _Sample bat output_ 33 | 34 | 我将别名 `cat` 指到了 `bat` 命令: 35 | 36 | ``` bash 37 | alias cat='bat' 38 | ``` 39 | 40 | * [安装指引](https://github.com/sharkdp/bat) [3] 41 | 42 | ### prettyping > ping 43 | 44 | `ping` 非常有用,当我碰到 “糟了,是不是 X 挂了?/ 我的网不通了?” 这种情况下我最先想到的工具就是它了。但是 `prettyping`(“prettyping” 可不是指 “pre typing”)在 `ping` 的基础上加了友好的输出,这可让我感觉命令行友好了很多呢。 45 | 46 | ![](https://dn-linuxcn.qbox.me/data/attachment/album/201810/29/204655zcznq3x70xjexzv3.gif) 47 | 48 | _Sample ping output_ 49 | 50 | 我也将 `ping` 用别名链接到了 `prettyping` 命令: 51 | 52 | ``` bash 53 | alias ping='prettyping --nolegend' 54 | ``` 55 | 56 | * [安装指引](http://denilson.sa.nom.br/prettyping/) [4] 57 | 58 | ### fzf > ctrl+r 59 | 60 | 在终端里,使用 `ctrl+r` 将允许你在命令历史里[反向搜索](https://lifehacker.com/278888/ctrl%252Br-to-search-and-other-terminal-history-tricks) [5] 使用过的命令,这是个挺好的小技巧,尽管它有点麻烦。 61 | 62 | `fzf` 这个工具相比于 `ctrl+r` 有了**巨大的**进步。它能针对命令行历史进行模糊查询,并且提供了对可能的合格结果进行全面交互式预览。 63 | 64 | > 此处应有视频,地址: [https://dn-linuxcn.qbox.me/static/video/cli%20-%20fuzzy-history-217497007.mp4](https://dn-linuxcn.qbox.me/static/video/cli%20-%20fuzzy-history-217497007.mp4)[](https://dn-linuxcn.qbox.me/static/video/cli%20-%20fuzzy-history-217497007.mp4)[6] 65 | 66 | 除了搜索命令历史,`fzf` 还能预览和打开文件,我在下面的视频里展示了这些功能。 67 | 68 | > 此处应有视频,地址: [https://dn-linuxcn.qbox.me/static/video/cli%20-%20fuzzy%20enhanced-286345188.mp4](https://dn-linuxcn.qbox.me/static/video/cli%20-%20fuzzy%20enhanced-286345188.mp4)[](https://dn-linuxcn.qbox.me/static/video/cli%20-%20fuzzy%20enhanced-286345188.mp4)[7] 69 | 70 | 为了这个预览的效果,我创建了一个叫 `preview` 的别名,它将 `fzf` 和前文提到的 `bat` 组合起来完成预览功能,还给上面绑定了一个定制的热键 `ctrl+o` 来打开 VS Code: 71 | 72 | ``` bash 73 | alias preview="fzf --preview 'bat --color \"always\" {}'" 74 | # 支持在 VS Code 里用 ctrl+o 来打开选择的文件 75 | export FZF_DEFAULT_OPTS="--bind='ctrl-o:execute(code {})+abort'" 76 | ``` 77 | 78 | * [安装指引](https://github.com/junegunn/fzf) [8] 79 | 80 | ### htop > top 81 | 82 | `top` 是当我想快速诊断为什么机器上的 CPU 跑的那么累或者风扇为什么突然呼呼大做的时候首先会想到的工具。我在生产环境也会使用这个工具。讨厌的是 Mac 上的 `top` 和 Linux 上的 `top` 有着极大的不同(恕我直言,应该是差的多)。 83 | 84 | 不过,`htop` 是对 Linux 上的 `top` 和 Mac 上蹩脚的 `top` 的极大改进。它增加了包括颜色输出,键盘热键绑定以及不同的视图输出,这对理解进程之间的父子关系有极大帮助。 85 | 86 | 一些很容易上手的热键: 87 | 88 | * `P` —— 按 CPU 使用率排序 89 | * `M` —— 按内存使用排序 90 | * `F4` —— 用字符串过滤进程(例如只看包括 node 的进程) 91 | * `space` —— 锚定一个单独进程,这样我能观察它是否有尖峰状态 92 | 93 | ![](https://dn-linuxcn.qbox.me/data/attachment/album/201810/29/204657hnfne1peg857gtdq.jpg) 94 | 95 | _Sample htop output_ 96 | 97 | 在 Mac Sierra 上 htop 有个奇怪的 bug,不过这个 bug 可以通过以 root 运行来绕过(我实在记不清这个 bug 是什么,但是这个别名能搞定它,有点讨厌的是我得每次都输入 root 密码。): 98 | 99 | ``` bash 100 | alias top="sudo htop" # 给 top 加上别名并且绕过 Sierra 上的 bug 101 | ``` 102 | 103 | * [安装指引](http://hisham.hm/htop/) [9] 104 | 105 | ### diff-so-fancy > diff 106 | 107 | 我非常确定我是几年前从 Paul Irish 那儿学来的这个技巧,尽管我很少直接使用 `diff`,但我的 git 命令行会一直使用 `diff`。`diff-so-fancy` 给了我代码语法颜色和更改字符高亮的功能。 108 | 109 | ![](https://dn-linuxcn.qbox.me/data/attachment/album/201810/29/204658r8zajeo2b98ase4b.jpg) 110 | 111 | _Sample diff output_ 112 | 113 | 在我的 `~/.gitconfig` 文件里我用了下面的选项来打开 `git diff` 和 `git show` 的 `diff-so-fancy` 功能。 114 | 115 | ``` bash 116 | [pager] 117 | diff = diff-so-fancy | less --tabs=1,5 -RFX 118 | show = diff-so-fancy | less --tabs=1,5 -RFX 119 | ``` 120 | 121 | * [安装指引](https://github.com/so-fancy/diff-so-fancy) [10] 122 | 123 | ### fd > find 124 | 125 | 尽管我使用 Mac,但我绝不是 Spotlight 的粉丝,我觉得它的性能很差,关键字也难记,加上更新它自己的数据库时会拖慢 CPU,简直一无是处。我经常使用 [Alfred](https://www.alfredapp.com/)[11],但是它的搜索功能也不是很好。 126 | 127 | 我倾向于在命令行中搜索文件,但是 `find` 的难用在于很难去记住那些合适的表达式来描述我想要的文件。(而且 Mac 上的 `find` 命令和非 Mac 的 `find` 命令还有些许不同,这更加深了我的失望。) 128 | 129 | `fd` 是一个很好的替代品(它的作者和 `bat` 的作者是同一个人)。它非常快而且对于我经常要搜索的命令非常好记。 130 | 131 | 几个上手的例子: 132 | 133 | ``` bash 134 | $ fd cli # 所有包含 "cli" 的文件名 135 | $ fd -e md # 所有以 .md 作为扩展名的文件 136 | $ fd cli -x wc -w # 搜索 "cli" 并且在每个搜索结果上运行 `wc -w` 137 | ``` 138 | 139 | ![](https://dn-linuxcn.qbox.me/data/attachment/album/201810/29/204700varcm94gce19m91g.png) 140 | 141 | _Sample fd output_ 142 | 143 | * [安装指引](https://github.com/sharkdp/fd/) [12] 144 | 145 | ### ncdu > du 146 | 147 | 对我来说,知道当前磁盘空间被什么占用了非常重要。我用过 Mac 上的 [DaisyDisk](https://daisydiskapp.com/)[13],但是我觉得那个程序产生结果有点慢。 148 | 149 | `du -sh` 命令是我经常会运行的命令(`-sh` 是指结果以 “汇总” 和“人类可读”的方式显示),我经常会想要深入挖掘那些占用了大量磁盘空间的目录,看看到底是什么在占用空间。 150 | 151 | `ncdu` 是一个非常棒的替代品。它提供了一个交互式的界面并且允许快速的扫描那些占用了大量磁盘空间的目录和文件,它又快又准。(尽管不管在哪个工具的情况下,扫描我的 home 目录都要很长时间,它有 550G) 152 | 153 | 一旦当我找到一个目录我想要 “处理” 一下(如删除,移动或压缩文件),我会使用 `cmd` + 点击 [iTerm2](https://www.iterm2.com/)[14] 顶部的目录名字的方法在 Finder 中打开它。 154 | 155 | ![](https://dn-linuxcn.qbox.me/data/attachment/album/201810/29/204701qk3aaia5w0z9505o.png) 156 | 157 | _Sample ncdu output_ 158 | 159 | 还有另外[一个叫 nnn 的替代选择](https://github.com/jarun/nnn) [15],它提供了一个更漂亮的界面,它也提供文件尺寸和使用情况,实际上它更像一个全功能的文件管理器。 160 | 161 | 我的 `du` 是如下的别名: 162 | 163 | ``` bash 164 | alias du="ncdu --color dark -rr -x --exclude .git --exclude node_modules" 165 | ``` 166 | 167 | 选项说明: 168 | 169 | * `--color dark` 使用颜色方案 170 | * `-rr` 只读模式(防止误删和运行新的 shell 程序) 171 | * `--exclude` 忽略不想操作的目录 172 | 173 | * [安装指引](https://dev.yorhel.nl/ncdu) [16] 174 | 175 | ### tldr > man 176 | 177 | 几乎所有的命令行工具都有一个相伴的手册,它可以被 `man <命令名>` 来调出,但是在 `man` 的输出里找到东西可有点让人困惑,而且在一个包含了所有的技术细节的输出里找东西也挺可怕的。 178 | 179 | 这就是 TL;DR 项目(LCTT 译注:英文里 “文档太长,没空去读” 的缩写)创建的初衷。这是一个由社区驱动的文档系统,而且可以用在命令行上。就我现在使用的经验,我还没碰到过一个命令没有它相应的文档,你[也可以做贡献](https://github.com/tldr-pages/tldr#contributing) [17]。 180 | 181 | ![](https://dn-linuxcn.qbox.me/data/attachment/album/201810/29/204703q98ze88c128p93ip.png) 182 | 183 | _Sample tldr output for fd_ 184 | 185 | 一个小技巧,我将 `tldr` 的别名链接到 `help`(这样输入会快一点……) 186 | 187 | ``` bash 188 | alias help='tldr' 189 | ``` 190 | 191 | * [安装指引](http://tldr-pages.github.io/) [18] 192 | 193 | ### ack || ag > grep 194 | 195 | `grep` 毫无疑问是一个强力的命令行工具,但是这些年来它已经被一些工具超越了,其中两个叫 `ack` 和 `ag`。 196 | 197 | 我个人对 `ack` 和 `ag` 都尝试过,而且没有非常明显的个人偏好,(也就是说它们都很棒,并且很相似)。我倾向于默认只使用 `ack`,因为这三个字符就在指尖,很好打。并且 `ack` 有大量的 `ack --bar` 参数可以使用!(你一定会体会到这一点。) 198 | 199 | `ack` 和 `ag` 默认都使用正则表达式来搜索,这非常契合我的工作,我能使用类似于 `--js` 或 `--html` 这种标识指定文件类型搜索。(尽管 `ag` 比 `ack` 在文件类型过滤器里包括了更多的文件类型。) 200 | 201 | 两个工具都支持常见的 `grep` 选项,如 `-B` 和 `-A` 用于在搜索的上下文里指代 “之前” 和“之后”。 202 | 203 | ![](https://dn-linuxcn.qbox.me/data/attachment/album/201810/29/204704c433kka72aki0kk7.png) 204 | 205 | _Sample ack output with grep args_ 206 | 207 | 因为 `ack` 不支持 markdown(而我又恰好写了很多 markdown),我在我的 `~/.ackrc` 文件里加了以下定制语句: 208 | 209 | ``` bash 210 | --type-set=md=.md,.mkd,.markdown 211 | --pager=less -FRX 212 | ``` 213 | 214 | * 安装指引:[ack](https://beyondgrep.com)[19],[ag](https://github.com/ggreer/the_silver_searcher)[20] 215 | * [关于 ack & ag 的更多信息](http://conqueringthecommandline.com/book/ack_ag) [21] 216 | 217 | ### jq > grep 及其它 218 | 219 | 我是 [jq](https://stedolan.github.io/jq)[22] 的忠实粉丝之一。当然一开始我也在它的语法里苦苦挣扎,好在我对查询语言还算有些使用心得,现在我对 `jq` 可以说是每天都要用。(不过从前我要么使用 `grep` 或者使用一个叫 [json](http://trentm.com/json/)[23] 的工具,相比而言后者的功能就非常基础了。) 220 | 221 | 我甚至开始撰写一个 `jq` 的教程系列(有 2500 字并且还在增加),我还发布了一个[网页工具](https://jqterm.com) [24] 和一个 Mac 上的应用(这个还没有发布。) 222 | 223 | `jq` 允许我传入一个 JSON 并且能非常简单的将其转变为一个使用 JSON 格式的结果,这正是我想要的。下面这个例子允许我用一个命令更新我的所有 node 依赖。(为了阅读方便,我将其分成为多行。) 224 | 225 | ``` bash 226 | $ npm i $(echo $(\ 227 | npm outdated --json | \ 228 | jq -r 'to_entries | .[] | "\(.key)@\(.value.latest)"' \ 229 | )) 230 | ``` 231 | 232 | 上面的命令将使用 npm 的 JSON 输出格式来列出所有过期的 node 依赖,然后将下面的源 JSON 转换为: 233 | 234 | ``` json 235 | { 236 | "node-jq": { 237 | "current": "0.7.0", 238 | "wanted": "0.7.0", 239 | "latest": "1.2.0", 240 | "location": "node_modules/node-jq" 241 | }, 242 | "uuid": { 243 | "current": "3.1.0", 244 | "wanted": "3.2.1", 245 | "latest": "3.2.1", 246 | "location": "node_modules/uuid" 247 | } 248 | } 249 | ``` 250 | 251 | 转换结果为: 252 | 253 | ``` bash 254 | node-jq@1.2.0 255 | uuid@3.2.1 256 | ``` 257 | 258 | 上面的结果会被作为 `npm install` 的输入,你瞧,我的升级就这样全部搞定了。(当然,这里有点小题大做了。) 259 | 260 | ### 很荣幸提及一些其它的工具 261 | 262 | 我也在开始尝试一些别的工具,但我还没有完全掌握它们。(除了 `ponysay`,当我打开一个新的终端会话时,它就会出现。) 263 | 264 | * [ponysay](https://github.com/erkin/ponysay)[25] > `cowsay` 265 | * [csvkit](https://csvkit.readthedocs.io/en/1.0.3/)[26] > `awk 及其它` 266 | * [noti](https://github.com/variadico/noti)[27] > `display notification` 267 | * [entr](http://www.entrproject.org/)[28] > `watch` 268 | 269 | ### Mac 上怎么调节 Launchpad(启动台) 的图标大小,基本就是三行终端命令 270 | 271 | ``` bash 272 | # 先调整每列显示多少个 273 | $ defaults write com.apple.dock springboard-rows -int 6 274 | 275 | # 再调整每行显示多少个 276 | $ defaults write com.apple.dock springboard-columns -int 11 277 | 278 | # 重置一下 279 | $ defaults write com.apple.dock ResetLaunchPad -bool TRUE;killall Dock 280 | ``` 281 | 282 | ### 原文链接 283 | 284 | * [https://linux.cn/article-10171-1.html?utm_source=rss&utm_medium=rss](https://linux.cn/article-10171-1.html?utm_source=rss&utm_medium=rss) 285 | -------------------------------------------------------------------------------- /《代码整洁之道》.md: -------------------------------------------------------------------------------- 1 | # 《代码整洁之道》 2 | 3 | ## 第一章 整洁代码 4 | 5 | ### 1、赶上期限的唯一方法:始终尽可能保持代码整洁 6 | 7 | ### 2、整洁的代码只做好一件事 8 | 9 | ### 3、整本书的主旨,不要重复代码,只做一件事,表达力,小规模抽象 10 | 11 | ### 4、要想干得快,要想快点做完,要想轻松写代码,先让代码易读吧 12 | 13 | ### 5、让每次签入时,代码都比签出时干净 14 | 15 | ## 第二章 有意义的命名 16 | 17 | ### 1、名副其实 18 | 19 | > 如果名称需要注释来补充,那就不算是名副其实。 20 | 21 | ### 2、避免误导 22 | 23 | > 别用 xxxList 来指称一组账号,除非它真的是 List 类型。(用 xxxGroup/bunchOfxxx/xxxs 代替更好) 24 | 25 | ### 3、做有意义的区分 26 | 27 | > 不要使用数字区分变量 / 函数命名。如 a1,a2... 28 | > 不要添加废话区分命名。如:ProductInfo 和 ProductData 29 | 30 | ### 4、使用读得出来的名称 31 | 32 | > 比如日期:用 generationTimestamp,而不要使用 genymdhms。 33 | 34 | ### 5、使用可搜索的名称 35 | 36 | > 单字母和数字常量很难搜出。使用宏或者变量命名这类数据。 37 | 38 | ### 6、避免使用编码 39 | 40 | > 不必用前缀表示成员变量。 41 | 42 | ### 7、避免思维映射 43 | 44 | ### 8、类名 45 | 46 | > 类名和对象应该是名词或名词短语。 47 | 48 | ### 9、方法名 49 | 50 | > 方法名应该是动词或动词短语。 51 | 52 | ### 10、别扮可爱 53 | 54 | ### 11、每个概念对应一个词 55 | 56 | ### 12、别用双关语 57 | 58 | > 避免将同一个单词用于不同目的。 59 | 60 | ### 13、使用解决方案领域名称 61 | 62 | > 尽可能使用 IT 类术语 63 | 64 | ### 14、使用源自所涉问题领域的名称 65 | 66 | ### 15、使用有意义的语境 67 | 68 | > 如:使用 addrState 代替 state 69 | 70 | ### 16、不要添加没用的语境 71 | 72 | > 如:不要用 GSD 代替 GasStationDeluxe 这样类似的短语。 73 | 74 | ## 第三章 函数 75 | 76 | ### 1、函数的第一规则是要短小,第二规则是还要更短小 77 | 78 | ### 2、函数的缩进层数不该多于一层或两层 79 | 80 | ### 3、函数应该做一件事,做好这件事,只做这一件事 81 | 82 | ### 4、要判断函数是否不止做了一件事,看是否能再拆出一个函数,该函数不仅是单纯地重新诠释其实现 83 | 84 | ### 5、函数参数,最理想的参数是 0, 其次是 1, 再次是 2\. 尽量避免 3 个。有足够特殊的理由才能用 3 个以上函数 85 | 86 | ### 6、如果函数看起来需要两个,三个或三个以上参数,就说明其中一些参数应该封装成类了 87 | 88 | ### 7、函数不应有副作用,如,检查密码的函数不应该有初始化 Session 的步骤 89 | 90 | ### 8、把指令和询问分隔开来 91 | 92 | ### 9、别重复自己 93 | 94 | ### 10、如何做到:先想些什么就写什么,然后再打磨它 95 | 96 | ## 第四章 注释 97 | 98 | ### 1、注释的恰当用法是弥补我们在用代码表达意图时遭遇的失败 99 | 100 | ### 2、注释会撒谎,因为修改代码后并不会让注释随之变动 101 | 102 | ### 3、注释不会美化糟糕的代码 103 | 104 | ### 4、与其花时间美化代码,不如花时间清洁代码 105 | 106 | ### 好注释 107 | 108 | * 法律信息 109 | * 提供信息的注释 110 | * 对意图的注释 111 | * 阐释 112 | * 警示 113 | * TODO 114 | * 放大:放大某种看起来不合理之物的重要性 115 | * 公共 API 中的 javadoc 116 | 117 | ### 坏注释 118 | 119 | * 喃喃自语 120 | * 多余的注释 121 | * 误导性注释 122 | * 循规式注释 123 | * 日志式注释 124 | * 废话注释 125 | * 可怕的废话 126 | * 能用函数或变量时就别用注释 127 | * 位置标记 128 | * 括号后面的注释 129 | * 归属和署名 130 | * 注释掉的代码(别这么干) 131 | * html 注释 132 | * 非本地信息 133 | * 信息过多 134 | * 不明显的联系 135 | * 函数头 136 | * 非公共代码中的 javadoc 137 | 138 | ## 第五章 格式 139 | 140 | ### 1、代码格式很重要,关乎沟通 141 | 142 | ### 2、实体变量应该在类的顶部声明 143 | 144 | ### 3、相关函数。若某个函数调用了另一个,就应该把它们放到一起。而且调用着应该尽可能放在被调用着上面 145 | 146 | ### 4、四则运算时,运算级较高的符号可以不用空格隔开 147 | 148 | ### 5、每个程序员都有自己喜欢的格式规则,但如果在一个团队中工作,就是团队说了算 149 | 150 | ## 第六章 对象和数据结构 151 | 152 | ### 1、隐藏实现并非只是变量之间放上一个函数层那么简单。隐藏实现关乎抽象。类并不简单地用取值器和赋值器将变量推向外间,而是暴露抽象接口,以便用户无需了解数据的实现便能操作数据本体 153 | 154 | ### 2、要以最好的方式呈现某个对象包含的数据,需要做严肃的思考 155 | 156 | ### 3、过程式代码便于在不改动既有函数的前提下添加新类 157 | 158 | ### 4、得墨耳律:模块不应了解它所操作对象的内部情形 159 | 160 | ### 例如:类 C 的 f 方法只应调用以下对象的方法 161 | 162 | > C 由 f 创建的对象 163 | > 由 C 的实体变量持有的对象 164 | > 即:方法不应调用由任何函数返回的对象的方法。 165 | 166 | ## 第七章 错误处理 167 | 168 | ### 1、使用异常而非返回码。 先写 try、catch、finally 语句 169 | 170 | ### 2、使用不可控异常 171 | 172 | ### 3、给出异常发生的环境说明 173 | 174 | > 应创建信息充分的错误信息,并和异常一起传递出去。在消息中,包括失败的操作和失败的类型。如果你的应用程序由日志系统,传递足够的信息给 catch 块,并记录下来。 175 | 176 | ### 4、依调用者需要定义异常类 177 | 178 | ### 5、定义常规流程 179 | 180 | ### 6、别返回 null 值 181 | 182 | ### 7、别传递 null 值 183 | 184 | ## 第九章 单元测试 185 | 186 | ### 1、TDD 三定律 187 | 188 | 1. 在编写不能通过的单元测试前,不可编写生产代码。 189 | 2. 只可编写刚好无法通过的单元测试,不能编译也不算通过。 190 | 3. 只可编写刚好足以通过当前失败测试的生产代码。 191 | 192 | ### 2、保持测试整洁 193 | 194 | ### 3、脏测试等同于没测试 195 | 196 | ### 4、测试代码和生产代码一样重要 197 | 198 | ### 5、整洁的测试三要素:可读性,可读性和可读性 199 | 200 | ### 6、每个测试一个断言 201 | 202 | ### 7、每个测试只测试一个概念 203 | 204 | ### 8、F.I.R.S.T 205 | 206 | > Fast(快速)、Independent(独立)、Repeatable(可重复)、Self-Validating(自足验证)、Timely(及时) 207 | 208 | ## 第十章 类 209 | 210 | ### 1、类应该短小 211 | 212 | ### 2、用权责衡量类的大小 213 | 214 | ### 3、如果无法为某个类命以精确的名称,这个类大概太长了 215 | 216 | ### 4、SRP,单一权责原则,类或模块应有且只有一条加以修改的理由 217 | 218 | ### 5、系统应该有许多短小的类而不是少量巨大的类组成。每个小雷封装一个权责,只有一个修改的原因,并与少数其他类一起协同达成期望的系统行为 219 | 220 | ### 6、内聚:如果一个类中的每个变量都被每个方法所使用,则该类具有最大的内聚性 221 | 222 | ## 第十一章 系统 223 | 224 | ### 1、将构造与使用分开的方法之一是将全部构造过程搬迁到 main 或被称之为 main 的模块中,设计系统的其他部分时,假设所有对象都已正确构造和设置 225 | 226 | ### 2、使用工厂方法,让程序负责确定何时创建对象 227 | 228 | ### 3、AOP 切面编程 229 | 230 | ## 第十二章 迭进 231 | 232 | ### 1、简单设计四条规则 233 | 234 | 1. 运行所有测试; 235 | 2. 不可重复; 236 | 3. 表达了程序员的意图; 237 | 4. 尽可能减少类和方法的数量。 238 | 239 | ### 2、极其雷同的代码就是重复 240 | 241 | ### 3、要想实现大规模复用,必须理解如何实现小规模复用 242 | 243 | ### 4、模板方法模式是一种移除高层级重复的通用技巧 244 | 245 | ## 第十三章 并发编程 246 | 247 | ### 1、对象是过程的抽象,线程是调度的抽象 248 | 249 | ### 2、并发是一种解耦策略,帮助我们把做什么(目的)和何时(时间)做分解开 250 | 251 | ### 3、并发会在性能和编写额外代码上增加一些开销 252 | 253 | ### 4、正确的并发是复杂的,即便对于简单的问题也是如此 254 | 255 | ### 5、并发缺陷并非总能重现,所以常被看做偶发事件而忽略,未被当作真的缺陷对待 256 | 257 | ### 6、并发常常需要对设计策略的根本性修改 258 | 259 | ### 7、并发防御原则 260 | 261 | * SRP,分离并发相关代码和其他代码。 262 | * 推论:限制数据作用域。 263 | * 推论:使用数据复本,避免共享数据的好方法之一就是一开始就避免共享数据。 264 | * 推论:线程应尽可能独立。尝试将数据分解到可独立线程(可能在不同处理器上)操作的独立子集。 265 | 266 | ### 8、并发执行模型 267 | 268 | * 生产者-消费者 269 | * 读者-作者 270 | * 宴席哲学家 271 | 272 | ### 9、学习这些基础算法,理解其解决方案 273 | 274 | ### 10、在你认为自己完成某个函数之前,确认自己理解了它是怎么工作的。通过全部测试还不够好。你必须知道解决方案是正确的。获得这种知识和理解的最好途径,往往是重构函数,得到某种整洁而足具表达力、清楚呈示如何工作的东西 275 | 276 | ### 11、用多态替代 If/Else 或 Switch/Case 277 | -------------------------------------------------------------------------------- /应用代码分层.md: -------------------------------------------------------------------------------- 1 | # 应用代码分层 2 | 3 | 我们在写应用里的代码时根据代码负责的不同任务讲其分为五大块`Controller`, `Repository`, `Service`, `Model`, `View`。 4 | 5 | - `Model` 数据模型, 数据模型面向的是数据层,在这里我们只关心数据表的问题,在 Model 中应该只定义数据与对象映射相关的属性和方法如:表名、主键名、是否让 laravel 管理时间字段等属性,以及模型关联、查询作用域等方法。其他与数据表无关的业务逻辑都不应出现在这里。 6 | - `Repository` 数据逻辑访问层,由它来对接 Model 层,理论上有一个 Model 就会有一个相应的`Repository`,除了做最基础的数据访问外与数据相关的逻辑也放在这里,如果一个相对复杂的数据应用到了`Repository`对应的`Model`外其他`Model`的数据,不要直接去访问相关`Model`,应该由`Repository`调用相关`Model`的`Repository`。`Repository`是具体`interface`的实现,比如做订单相关的业务,应该有`OrderRepositoryInterface`定义`Order`数据交互流程中必须要实现的方法然后由`OrderRepository`去具体实现,之后将`OrderRepositoryInterface`和`OrderRepository`注册到服务容器中,解析时直接使用`OrderRepositoryInterface`解析出具体实现,这样消费层既不需要关心数据来自哪里是`Mysql`还是`MongoDB`,也给项目提供了足够的灵活性。当数据来源从`Mysql`更改为`MongoDB`后,我们只需要重新写一个实现类`OrderMongoRepository`然后将服务容器里`OrderRepositoryInterface`的实现切换成`OrderMongoRepository`就好,消费层完全不需要改动。 7 | (Repository 是我之前一直觉得在程序设计中特别多余而现在觉得特别重要的一个 Layer,之前在 Service 中揉进去了 Repository 的职能,后续会把相关的 Example 也做一下修改) 8 | - `Service` 项目中除了数据的 CRUD 还会有图片上传、请求外部 API 获取数据、发送邮件等等其他这些功能,这些功能应该定义在`Service`层。 9 | - `Controller` 控制器,面向的对象是一个完整的页面或者是接口,其主要职责是作为接收请求和发送响应的中控程序,通过调度项目中的 Service、 Repository 等来完成请求、组合响应数据,并通过页面响应或者接口数据的形式将响应返回给客户端。 10 | - `View` 视图, 负责渲染 HTML 响应,使用 Laravel 自带的 blade 模版引擎,并且应该尽量减少 PHP 代码。 11 | 12 | 总结:所以如果一个请求对应的业务逻辑相当复杂,我们可以通过 Controller 方法调用多个 Service 方法(单一逻辑)来完成这个复杂的逻辑,在 Service 方法中我们通过多个 Model 操作来实现更新、获取数据。通过这种原则来对复杂逻辑进行解耦。 13 | 14 | 我们通过看两个例子来更好的理解代码如何分层: 15 | 16 | ## 代码示例 17 | 18 | ### Example 1: 应该在哪里写 SQL 操作 19 | 20 | 如果一个查询在项目中只会用到一次,那么我们直接在 Controller 方法里写这个查询就很好, 举例来说你想查出所有的管理员用户: 21 | 22 | ``` php 23 | $admins = User::where('type', 'admin')->get(); 24 | ``` 25 | 26 | 现在假设你需要在不止一个 Controller 方法中用到这个查询, 你可以在`UserRepository`类里包装对`User`模型的访问: 27 | 28 | ``` php 29 | class UserRepository 30 | { 31 | public function getAlladmins() 32 | { 33 | return User::where('type', 'admin')->get(); 34 | } 35 | } 36 | ``` 37 | 38 | 现在你可以在用到`UserRepository`的`Controller`中通过依赖注入`UserRepository`, 然后通过这个 UserRepository 方法获取所有管理员用户: 39 | 40 | ``` php 41 | //Controller 42 | public function __construct(UserRepository $UserRepository) 43 | { 44 | $this->UserRepository = $UserRepository; 45 | } 46 | //Controller action 47 | public function index() 48 | { 49 | $admins = $this->UserRepository->getAllAdmins(); 50 | } 51 | ``` 52 | 53 | 最后,假设你还需要一个查询来计算管理员的数量, 可以在把这个查询封装到 UserService 的一个方法里: 54 | 55 | ``` php 56 | public function getAdminNum() 57 | { 58 | return User::where('type', 'admin')->count(); 59 | } 60 | ``` 61 | 62 | 这样写是 OK 的,但是你可能已经注意到了`User::where('type', 'admin')`这个片段在`getAllAdmins`这个查询里也有用到,所以我们可以用查询作用域来改进它(查询作用域也会让你的代码可读性变得更高): 63 | 64 | ``` php 65 | //UserModel 66 | public function scopeAdmins($query) 67 | { 68 | return $query->where('type', 'admin'); 69 | } 70 | ``` 71 | 72 | 然后在 UserRepository 里我们可以向下面这样重写它的查询: 73 | 74 | ``` php 75 | //UserRepository 76 | public function getAllAdmins() 77 | { 78 | return User:admins()->get(); 79 | } 80 | 81 | public function getAdminNum() 82 | { 83 | return User::admins()->count(); 84 | } 85 | ``` 86 | 87 | 就像上面说的那样在 Model 中我们应该撇开业务逻辑,面向数据表进行抽象,只定义表相关的属性、模型关联和查询作用域, 具体怎么应用 Model 中定义的这些内容, 那是 Controller 层和 Service 层要关心的事情。 88 | 89 | ### Example2: 通过 Service 类提高代码复用率 90 | 91 | 我们在做 CMS 系统管理内容时, 通常都会涉及到文章的上下线,置顶等操作。假设在系统中我们会用两个数据表分别存储文章和置顶, 在项目中对应两个 Model: Article 和 TopArticle。 92 | 93 | 假设我们需要实现下线文章的功能,如果文章是置顶文章,还要把文章取消置顶,我们在 ArticleService 里包装这个操作: 94 | 95 | ``` php 96 | public function setArticleOffline(Article $article) 97 | { 98 | if ($article->is_top == 1) {//如果是置顶文章需要将文章取消置顶 99 | $this->cancelTopArticle($article); 100 | } 101 | $article->status = Article::STATUS_OFFLINE; 102 | $article->offline_time = date('Y-m-d H:i:s'); 103 | $article->save(); 104 | 105 | return true; 106 | } 107 | 108 | /** 109 | * 取消文章的置顶 110 | * @param \App\Models\Article $article 111 | */ 112 | public function cancelTopArticle($article) 113 | { 114 | if (TopArticle::specificArticle($article->id)->count()) { 115 | //删除置顶表里的记录(待上线的置顶文章上线后置顶表中才能有相应的记录) 116 | TopArticle::specificArticle($article->id)->delete(); 117 | } 118 | //将文章的is_top字段置为0 119 | $article->is_top = 0; 120 | $article->save(); 121 | 122 | return true; 123 | } 124 | ``` 125 | 126 | 在 Controller 的 Action 里我们只需要负责验证接收来的参数,查询文章对象传递给 Service 来做下线操作, 这里之所以把取消置顶也单独提取出来是因为通常 CMS 系统里还有单独的文章取消置顶功能。 127 | 128 | ``` php 129 | //ArticleController 130 | public function setArticleOff(Request $request, ArticleService $artService) 131 | { 132 | ...//表单验证 133 | 134 | $article = Article::find($request->get('article_id')); 135 | $this->articleService->setArticleOffline($article); 136 | 137 | ... 138 | } 139 | ``` 140 | 141 | 除了上面讲到的主动下线文章的功能, 一般的文章系统里还会有定时上下线文章的功能, 因为我们在 ArticleService 里包装了下线文章的功能, 所以在设置定时任务时就可以再次调用 setArticleOffline 方法来完成文章下线的功能: 142 | 143 | ``` php 144 | //App\Console\Commands\ArticleCommand 145 | public function __construct(ArticleService $articleService) 146 | { 147 | $this->articleService = $articleService; 148 | parent::__construct(); 149 | } 150 | 151 | public function handle() 152 | { 153 | $operation = $this->argument('operation'); 154 | switch ($operation) { 155 | case 'offline': 156 | $this->setOffline(); 157 | break; 158 | default: 159 | break; 160 | } 161 | 162 | public function setOffline() 163 | { 164 | ......//前置条件查出要下线的文章 165 | $this>articleService>setArticleOffline($article); 166 | ...... 167 | } 168 | ``` 169 | 170 | 上面两个例子简单说明了我们把代码分层后每个层里应该写什么类型的程序,以及代码分层后在可读性、耦合性、维护成本等方面带来的收益。 171 | 172 | ## 原文链接 173 | 174 | * [https://github.com/kevinyan815/laravel_best_practices_cn/blob/master/src/CodeConvention/CodeLayer.md](https://github.com/kevinyan815/laravel_best_practices_cn/blob/master/src/CodeConvention/CodeLayer.md) 175 | -------------------------------------------------------------------------------- /正则表达式不要背.md: -------------------------------------------------------------------------------- 1 | # 正则表达式不要背 2 | 3 | ## 正则表达式到底是什么 4 | 5 | 正则表达式 (Regular Expression) 其实就是一门工具,**目的**是为了字符串模式匹配,从而实现搜索和替换功能。它起源于上个 20 世纪 50 年代科学家在数学领域做的一些研究工作,后来才被引入到计算机领域中。从它的命名我们可以知道,它是一种**用来描述规则的表达式**。而它的底层原理也十分简单,就是使用状态机的思想进行模式匹配。大家可以利用 [regexper.com](https://link.juejin.im?target=https%3A%2F%2Fregexper.com%2F) 这个工具很好地可视化自己写的正则表达式: 6 | 7 | 如`/\d\w+/`这个正则生成的状态机图: 8 | 9 | ![](https://user-gold-cdn.xitu.io/2019/5/16/16abe9d9357f691c?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) 10 | 11 | 对于具体的算法实现,大家如果感兴趣可以阅读《算法导论》。 12 | 13 | ## 从字符出发 14 | 15 | 我们学习一个系统化的知识,一定要从其基础构成来了解。正则表达式的基本**组成元素**可以分为:**字符和元字符**。字符很好理解,就是基础的计算机字符编码,通常正则表达式里面使用的就是数字、英文字母。而元字符,也被称为特殊字符,是一些用来表示特殊语义的字符。如 ^ 表示非,| 表示或等。利用这些元字符,才能构造出强大的表达式模式 (pattern)。接下来,我们就来从这些基本单位出发,来学习一下如何构建正则表达式。 16 | 17 | ### 单个字符 18 | 19 | 最简单的正则表达式可以由简单的数字和字母组成,没有特殊的语义,纯粹就是一一对应的关系。如想在'apple'这个单词里找到‘a'这个字符,就直接用`/a/`这个正则就可以了。 20 | 21 | 但是如果想要匹配特殊字符的话,就得请出我们第一个元字符 **`\`**, 它是转义字符字符,顾名思义,就是让其后续的字符失去其本来的含义。举个例子: 22 | 23 | 我想匹配`*`这个符号,由于`*`这个符号本身是个特殊字符,所以我要利用转义元字符`\`来让它失去其本来的含义: 24 | 25 | ``` js 26 | /\*/ 27 | ``` 28 | 29 | 如果本来这个字符不是特殊字符,使用转义符号就会让它拥有特殊的含义。我们常常需要匹配一些特殊字符,比如空格,制表符,回车,换行等, 而这些就需要我们使用转义字符来匹配。为了便于记忆,我整理了下面这个表格,并附上记忆方式: 30 | 31 | | 特殊字符 | 正则表达式 | 记忆方式 | 32 | | --- | --- | --- | 33 | | 换行符 | \n | **n**ew line | 34 | | 换页符 | \f | **f**orm feed | 35 | | 回车符 | \r | **r**eturn | 36 | | 空白符 | \s | **s**pace | 37 | | 制表符 | \t | **t**ab | 38 | | 垂直制表符 | \v | **v**ertical tab | 39 | | 回退符 | [\b] | **b**ackspace, 之所以使用 [] 符号是避免和 \ b 重复 | 40 | 41 | ### 多个字符 42 | 43 | 单个字符的映射关系是一对一的,即正则表达式的被用来筛选匹配的字符只有一个。而这显然是不够的,只要引入集合区间和通配符的方式就可以实现一对多的匹配了。 44 | 45 | 在正则表达式里,集合的定义方式是使用中括号`[`和`]`。如`/[123]/`这个正则就能同时匹配 1,2,3 三个字符。那如果我想匹配所有的数字怎么办呢?从 0 写到 9 显然太过低效,所以元字符`-`就可以用来表示区间范围,利用`/[0-9]/`就能匹配所有的数字, `/[a-z]/`则可以匹配所有的英文小写字母。 46 | 47 | 即便有了集合和区间的定义方式,如果要同时匹配多个字符也还是要一一列举,这是低效的。所以在正则表达式里衍生了一批用来同时匹配多个字符的简便正则表达式: 48 | 49 | | 匹配区间 | 正则表达式 | 记忆方式 | 50 | | --- | --- | --- | 51 | | 除了换行符之外的任何字符 | . | 句号, 除了句子结束符 | 52 | | 单个数字, [0-9] | \d | **d**igit | 53 | | 除了 [0-9] | \D | **not** **d**igit | 54 | | 包括下划线在内的单个字符,[A-Za-z0-9_] | \w | **w**ord | 55 | | 非单字字符 | \W | **not** **w**ord | 56 | | 匹配空白字符, 包括空格、制表符、换页符和换行符 | \s | **s**pace | 57 | | 匹配非空白字符 | \S | **not** **s**pace | 58 | 59 | ## 循环与重复 60 | 61 | 一对一和一对多的字符匹配都讲完了。接下来,就该介绍如何同时匹配多个字符。要实现多个字符的匹配我们只要多次循环,重复使用我们的之前的正则规则就可以了。那么根据循环次数的多与少,我们可以分为 0 次,1 次,多次,特定次。 62 | 63 | ### 0 | 1 64 | 65 | 元字符`?`代表了匹配一个字符或 0 个字符。设想一下,如果你要匹配`color`和`colour`这两个单词,就需要同时保证`u`这个字符是否出现都能被匹配到。所以你的正则表达式应该是这样的:`/colou?r/`。 66 | 67 | ### >= 0 68 | 69 | 元字符`*`用来表示匹配 0 个字符或无数个字符。通常用来过滤某些可有可无的字符串。 70 | 71 | ### >= 1 72 | 73 | 元字符`+`适用于要匹配同个字符出现 1 次或多次的情况。 74 | 75 | ### 特定次数 76 | 77 | 在某些情况下,我们需要匹配特定的重复次数,元字符`{`和`}`用来给重复匹配设置精确的区间范围。如'a'我想匹配 3 次, 那么我就使用`/a{3}/`这个正则,或者说'a'我想匹配至少两次就是用`/a{2,}/`这个正则。 78 | 79 | 以下是完整的语法: 80 | 81 | ``` js 82 | - {x}: x次 83 | 84 | - {min, max}: 介于min次到max次之间 85 | 86 | - {min, }: 至少min次 87 | 88 | - {0, max}: 至多max次 89 | ``` 90 | 91 | 由于这些元字符比较抽象,且容易混淆,所以我用了联想记忆的方式编了口诀能保证在用到的时候就能回忆起来。 92 | 93 | | 匹配规则 | 元字符 | 联想方式 | 94 | | --- | --- | --- | 95 | | 0 次或 1 次 | ? | 且**问**, 此事**有**还**无** | 96 | | 0 次或无数次 | * | 宇宙洪荒, **辰宿**列张:宇宙伊始,从无到有,最后星宿布满星空 | 97 | | 1 次或无数次 | + | **一加**, +1 | 98 | | 特定次数 | {x}, {min, max} | 可以想象成一个数轴,从一个点,到一个射线再到线段。min 和 max 分别表示了左闭右闭区间的左界和右界 | 99 | 100 | ## 位置边界 101 | 102 | 上面我们把字符的匹配都介绍完了,接着我们还需要位置边界的匹配。在长文本字符串查找过程中,我们常常需要限制查询的位置。比如我只想在单词的开头结尾查找。 103 | 104 | ### 单词边界 105 | 106 | 单词是构成句子和文章的基本单位,一个常见的使用场景是把文章或句子中的特定单词找出来。如: 107 | 108 | ``` js 109 | The cat scattered his food all over the room. 110 | ``` 111 | 112 | 我想找到`cat`这个单词,但是如果只是使用`/cat/`这个正则,就会同时匹配到`cat`和`scattered`这两处文本。这时候我们就需要使用边界正则表达式`\b`,其中 b 是 boundary 的首字母。在正则引擎里它其实匹配的是能构成单词的字符 (\w) 和不能构成单词的字符 (\W) 中间的那个位置。 113 | 114 | 上面的例子改写成`/\bcat\b/`这样就能匹配到`cat`这个单词了。 115 | 116 | ### 字符串边界 117 | 118 | 匹配完单词,我们再来看一下一整个字符串的边界怎么匹配。元字符`^`用来匹配字符串的开头。而元字符`$`用来匹配字符串的末尾。注意的是在长文本里,如果要排除换行符的干扰,我们要使用多行模式。试着匹配`I am scq000`这个句子: 119 | 120 | ``` js 121 | I am scq000. 122 | I am scq000. 123 | I am scq000. 124 | ``` 125 | 126 | 我们可以使用`/^I am scq000\.$/m`这样的正则表达式,其实 m 是 multiple line 的首字母。正则里面的模式除了 m 外比较常用的还有 i 和 g。前者的意思是忽略大小写,后者的意思是找到所有符合的匹配。 127 | 128 | 最后,总结一下: 129 | 130 | | 边界和标志 | 正则表达式 | 记忆方式 | 131 | | --- | --- | --- | 132 | | 单词边界 | \b | **b**oundary | 133 | | 非单词边界 | \B | **not** **b**oundary | 134 | | 字符串开头 | ^ | 小**头尖尖**那么大个 | 135 | | 字符串结尾 | $ | **终结**者,美国科幻电影,美元符 $ | 136 | | 多行模式 | m 标志 | **m**ultiple of lines | 137 | | 忽略大小写 | i 标志 | **i**gnore case, case-**i**nsensitive | 138 | | 全局模式 | g 标志 | **g**lobal | 139 | 140 | ## 子表达式 141 | 142 | 字符匹配我们介绍的差不多了,更加高级的用法就得用到子表达式了。通过嵌套递归和自身引用可以让正则发挥更强大的功能。 143 | 144 | 从简单到复杂的正则表达式演变通常要采用**分组、回溯引用和逻辑处理**的思想。利用这三种规则,可以推演出无限复杂的正则表达式。 145 | 146 | ### 分组 147 | 148 | 其中分组体现在:所有以`(`和`)`元字符所包含的正则表达式被分为一组,每一个分组都是一个**子表达式**,它也是构成高级正则表达式的基础。如果只是使用简单的`(regex)`匹配语法本质上和不分组是一样的,如果要发挥它强大的作用,往往要结合回溯引用的方式。 149 | 150 | ### 回溯引用 151 | 152 | 所谓回溯引用(backreference)指的是模式的后面部分引用前面已经匹配到的子字符串。你可以把它想象成是变量,回溯引用的语法像`\1`,`\2`,……, 其中`\1`表示引用的第一个子表达式,`\2`表示引用的第二个子表达式,以此类推。而`\0`则表示整个表达式。 153 | 154 | 假设现在要在下面这个文本里匹配两个连续相同的单词,你要怎么做呢? 155 | 156 | ``` js 157 | Hello what what is the first thing, and I am am scq000. 158 | ``` 159 | 160 | 利用回溯引用,我们可以很容易地写出`\b(\w+)\s\1`这样的正则。 161 | 162 | 回溯引用在替换字符串中十分常用,语法上有些许区别,用`$1`,`$2`... 来引用要被替换的字符串。下面以 js 代码作演示: 163 | 164 | ``` js 165 | var str = 'abc abc 123'; 166 | str.replace(/(ab)c/g,'$1g'); 167 | // 得到结果 'abg abg 123' 168 | ``` 169 | 170 | 如果我们不想子表达式被引用,可以使用**非捕获**正则`(?:regex)`这样就可以避免浪费内存。 171 | 172 | ``` js 173 | var str = 'scq000'. 174 | str.replace(/(scq00)(?:0)/, '$1,$2') 175 | // 返回scq00,$2 176 | // 由于使用了非捕获正则,所以第二个引用没有值,这里直接替换为$2 177 | ``` 178 | 179 | 有时,我们需要限制回溯引用的适用范围。那么通过前向查找和后向查找就可以达到这个目的。 180 | 181 | #### 前向查找 182 | 183 | 前向查找 (lookahead) 是用来限制后缀的。凡是以`(?=regex)`包含的子表达式在匹配过程中都会用来限制前面的表达式的匹配。例如`happy happily`这两个单词,我想获得以`happ`开头的副词,那么就可以使用`happ(?=ily)`来匹配。如果我想过滤所有以`happ`开头的副词,那么也可以采用**负前向查找**的正则`happ(?!ily)`,就会匹配到`happy`单词的`happ`前缀。 184 | 185 | #### 后向查找 186 | 187 | 介绍完前向查找,接着我们再来介绍一下它的反向操作:后向查找 (lookbehind)。后向查找(lookbehind) 是通过指定一个子表达式,然后从符合这个子表达式的位置出发开始查找符合规则的字串。举个简单的例子: `apple`和`people`都包含`ple`这个后缀,那么如果我只想找到`apple`的`ple`,该怎么做呢?我们可以通过限制`app`这个前缀,就能唯一确定`ple`这个单词了。 188 | 189 | ``` js 190 | /(?<=app)ple/ 191 | ``` 192 | 193 | 其中`(?<=regex)`的语法就是我们这里要介绍的后向查找。`regex`指代的子表达式会作为限制项进行匹配,匹配到这个子表达式后,就会继续向**后**查找。另外一种限制匹配是利用`(? 在对程序进行更新迭代的过程中,应当合理的避免修改类或方法的内部代码,而是优先选择通过继承、扩展等方式来实现。简而言之,就是:对扩展开放,对修改关闭。 6 | 7 | ## 里氏替换原则( Liskov Substitution Principle ) 8 | 9 | > 在实现子类的定义时,应该让它完全拥有替代父类进行工作的能力。简而言之,就是:子类对外要具与父类一致的方法或接口。 10 | 11 | ## 依赖倒置原则( Dependence Inversion Principle ) 12 | 13 | > 在对象或类的依赖关系定义上,父类或者其他上层实现不应该依赖于子类或者其他下层实现,通过这样,来避免依赖关系的耦合。 14 | 15 | ## 单一职责原则( Single Responsibility Principle ) 16 | 17 | > 在程序结构和依赖关系的定义上,要将类的功能职责充分理清,尽力减少类之间的耦合。避免对某个类进行修改时,牵一发动全身的连锁反应。 18 | 19 | ## 接口隔离原则( Interface Segregation Principle ) 20 | 21 | > 在对外接口的定义上,要避免庞大而臃肿的接口,而是进行责任细化的区分,避免冗余的代码实现。这对于提高内聚,提升系统灵活度是非常有效果的。 22 | 23 | ## 最少知识原则( Least Knowledge Principle ) 24 | 25 | > 在分配类的职责和建立依赖关系时,应该只关注于自身的功能实现和周围与之接触类的交互方式。避免类去考虑整个系统结构和处理流程,让类的职责清晰化,让系统的耦合度降低。 26 | 27 | ## 合成复用原则( Composite Reuse Principle ) 28 | 29 | > 在扩展功能的时候,要优先考虑水平形式的新增类或方法,而不是通过继承去实现。也就是通过功能的组合实现类,而不是通过基础去实现新的功能。这样可以提高类的可扩展性,减少系统的层次。 30 | 31 | ## 设计模式 32 | 33 | ### 面向对象的设计原则 34 | 35 | * 对接口编程,不要对实现编程 36 | * 使用对象之间的组合,减少对继承的使用 37 | * 抽象用于不同的事物,而接口用于事物的行为 38 | 39 | ### 设计模式的设计原则 40 | 41 | * 开闭原则:对扩展开放,对修改封闭 42 | * mean: 实例的内部不可修改,但可以增加新功能 43 | * 依赖倒转:对接口编程,依赖于抽象而不依赖于具体 44 | * mean: 就是把公共的拿出来,定义成抽象类、接口、抽象方法,然后大家再去实现这个抽 45 | 象,实现的方法各有不同,各个实体相互独立没有依赖,各个实体离开谁都能活 46 | * 接口隔离:使用多个接口,而不是对一个接口编程,去依赖降低耦合 47 | * mean: 就是抽象再抽象 48 | * 最少知道:减少内部依赖,尽可能的独立 49 | * mean: 实现依赖注入容器,把依赖的实体注入到一个实例(所谓容器) 50 | * 合成复用:多个独立的实体合成聚合,而不是使用继承 51 | * mean:尽可能不用继承,使用以上三种方式构成代码结构 52 | * 里氏代换:超类(父类)出现的地方,派生类(子类)都可以出现 53 | * mean:能用父类实现的子类也能实现 54 | 55 | ### 简单设计原则 56 | 57 | * 通过所有测试:及需求为上 58 | * 尽可能的消除重复:高内聚低耦合 59 | * 尽可能的清晰表达:可读性 60 | * 更少代码元素:常量,变量,函数,类,包 …… 都属于代码元素,降低复杂性 61 | * 以上四个原则的重要程度依次降低 62 | 63 | > 核心:高内聚松耦合(单一职责),外部依赖,实体对抽象编程,抽象就是分层 64 | 65 | --- 66 | 67 | ## 依赖倒置原则(Dependence Inversion Principle, DIP) 68 | 69 | > DIP 是一种软件设计的指导思想。传统软件设计中,上层代码依赖于下层代码,当下层出现变动时, 上层代码也要相应变化,维护成本较高。而 DIP 的核心思想是上层定义接口,下层实现这个接口, 从而使得下层依赖于上层,降低耦合度,提高整个系统的弹性。这是一种经实践证明的有效策略。 70 | 71 | ## 控制反转(Inversion of Control, IoC) 72 | 73 | > IoC 就是 DIP 的一种具体思路,DIP 只是一种理念、思想,而 IoC 是一种实现 DIP 的方法。 IoC 的核心是将类(上层)所依赖的单元(下层)的实例化过程交由第三方来实现。 一个简单的特征,就是类中不对所依赖的单元有诸如 `$component = new yii\component\SomeClass()`的实例化语句。 74 | 75 | ## 依赖注入(Dependence Injection, DI) 76 | 77 | > DI 是 IoC 的一种设计模式,是一种套路,按照 DI 的套路,就可以实现 IoC,就能符合 DIP 原则。 DI 的核心是把类所依赖的单元的实例化过程,放到类的外面去实现。 78 | 79 | ## 控制反转容器(IoC Container) 80 | 81 | > 当项目比较大时,依赖关系可能会很复杂。 而 IoC Container 提供了动态地创建、注入依赖单元,映射依赖关系等功能,减少了许多代码量。 Yii 设计了一个 yii\di\Container 来实现了 DI Container。 82 | 83 | ## 服务定位器(Service Locator) 84 | 85 | > Service Locator 是 IoC 的另一种实现方式, 其核心是把所有可能用到的依赖单元交由 Service Locator 进行实例化和创建、配置, 把类对依赖单元的依赖,转换成类对 Service Locator 的依赖。 DI 与 Service Locator 并不冲突,两者可以结合使用。 目前,Yii2.0 把这 DI 和 Service Locator 这两个东西结合起来使用,或者说通过 DI 容器,实现了 Service Locator。 86 | --------------------------------------------------------------------------------