-
Notifications
You must be signed in to change notification settings - Fork 0
/
content.json
1 lines (1 loc) · 136 KB
/
content.json
1
{"pages":[{"title":"","text":"{\"name\":\"Defense.ink\",\"short_name\":\"Defense.ink\",\"theme_color\":\"#2196f3\",\"background_color\":\"#2196f3\",\"display\":\"fullscreen\",\"orientation\":\"portrait\",\"Scope\":\"/\",\"start_url\":\"/\",\"icons\":[{\"src\":\"/img/icon-72x72.png\",\"sizes\":\"72x72\",\"type\":\"image/png\"}],\"splash_pages\":null}","link":"/manifest.json"},{"title":"404","text":"","link":"/404.html"},{"title":"About 安全贯穿于软件开发各个环节 - 404 页面","text":"Security accompanies every aspect of software development.安全贯穿于软件开发各个环节。GitHub Stats About MeHi! I’m Jack Liu (Jianqiu Liu). 👋 In me the tiger🐯 sniffs the rose🌹. Jack Liu GitHub profile trophy: WeChat QRcode Personal WeChat Subscriptions","link":"/about/index.html"},{"title":"Gallerys Random List","text":"","link":"/galleries/index.html"},{"title":"Music PlayList 🎵","text":"A collection of frequently-listened music playlist.🎵 Music Genre ClassificationPersonal NetEase Music 🎵 Light Music No. Awesome 1 All light Awesome 2 Solo Raúl Di Blasio 🎵 Songs Music No. Awesome 1 All songs Awesome","link":"/musics/index.html"},{"title":"Music Light Playlist","text":"A collection of frequently-listened music playlist.🎵 Exodus - Maksim Mrvica Crossroads - 7AND5 Snowy Lullaby (Original Mix) - K.S. Project Meadows of Heaven (Instrumental Version) - Nightwish Fly my wish - Edelis Do Not Go Away (Original Mix) - Martian Solo (Alone) - Raúl Di Blasio Wild Child - Enya","link":"/musics/light.html"},{"title":"Music Song Playlist","text":"A collection of frequently-listened music playlist.🎵 在路上 - 刘欢 海阔天空 - Beyond 水手 - 郑智化 平凡之路 (Live) 朴树 凡人歌 - 李宗盛 我有我路向 - 成龙 Andy - 阿杜 繁星之夜 - 朱桦 EconStories 1.Fight of the Century - EconStories 2.Fear the Boom and Bust - EconStories EconStories","link":"/musics/song.html"},{"title":"","text":"","link":"/projects/index.html"},{"title":"每段路(Bydj-jammy) by 吕方","text":"A collection of frequently-listened video playlist. 每段路(Bydj-jammy) by 吕方每段路(Bydj-jammy))","link":"/videos/bydj-jammy-lvfang.html"},{"title":"[Fight of the Century] Keynes vs. Hayek Economics Stories.","text":"A collection of frequently-listened video playlist. Fight of the Century: Keynes vs. Hayek - Economics Rap Battle Round One(【世纪之战】凯恩斯VS哈耶克 经济学说唱第1战) Fight of the Century: Keynes vs. Hayek - Economics Rap Battle Round Two(【世纪之战】凯恩斯VS哈耶克 经济学说唱第2战)","link":"/videos/econstories.html"},{"title":"How the Machine Works By Ray Dalio","text":"A collection of frequently-listened video playlist. How the Machine Works By Ray Dalio(经济这台机器是怎样运行的 作者·:瑞·达利奥) 原版:http://www.economicprinciples.org","link":"/videos/howtheeconmachine.html"},{"title":"Jay Chou Music","text":"A collection of frequently-listened video playlist. 【黑胶】周杰伦 - 黑暗三部曲以父之名 止战之殇 夜的第七章 【黑胶】周杰伦七里香 夜曲 晴天 周杰伦——出道以来所有单曲MV大盘点 含HD单曲【合集】","link":"/videos/jaychou.html"},{"title":"Video PlayList","text":"A collection of frequently-listened video playlist.(Reproduced reference) No. Name 1 周杰伦——出道以来所有单曲MV大盘点 含HD单曲【合集】 2 Fight of the Century: Keynes vs. Hayek - Economics Rap Battle Round One 【世纪之战】凯恩斯VS哈耶克 经济学说唱 3 How the Machine Works By Ray Dalio 经济这台机器是怎样运行的 作者·:瑞·达利奥 4 每段路 Bydj jammy – 吕方","link":"/videos/index.html"},{"title":"Solo (Raúl Di Blasio)","text":"Solo (Raúl Di Blasio)Author:Raúl Di BlasioPublish Date:1997-05-20Publish Company: RCA InternationalA personal favorite album.🎹 IntroLatin pianist Raul Di Blasio was born in 1949 in the small town of Zapala, Argentina, the son of a small farmer. He began his musical education at the age of six. He was first exposed to Latin music such as Tango and Bossa Nova, but was also heavily influenced by European classical composers such as Beethoven and Rachmaninov. As a teenager, however, Di Blasio became obsessed with the Beatles and quickly formed his own rock band, Los Diabolicos. The band achieved some success in its home country and did not break up until 1973. He then returned to classical music and toured South America in the mid-1970s. In 1978 Di Blasio went into musical hibernation for five years at a hotel in the Chilean city of Fonsi. At the end of this period of his life, he concentrated all his talent on making music. His debut single was released by EMI in 1983. It was a huge success and was hailed by the media as “the people’s pianist”. In 1987, he moved to Miami, USA. Three years later, he released erica on BMG, which sold more than one million copies in 1994. In order to hold a solo concert in 1997, Di Blasio toured the Far East. Solo (Raúl Di Blasio)","link":"/musics/light/Solo-Ra%C3%BAl-Di-Blasio.html"}],"posts":[{"title":"AI drawing ControlNet local implementation steps by stable-diffusion-webui(AI绘画ControlNet本地构建实施步骤 by stable-diffusion-webui)","text":"Install stable-diffusion-webui[Note]: Unable to install due to network problems, it is recommended to use GIT source pull installation(因网络问题导致无法安装,故建议使用GIT源码拉取安装方式) Due to the large size of the model file, it is recommended to ensure sufficient space before installation: At least [source code + data model + extension]25G(因模型文件较大,建议安装前确保有足够空间: 至少[源码+数据模型+扩展]25G) The PC terminal to be built is 🍎 macOS Ventura 13.4.1(c), and the Windows environment is built in much the same way.(构建PC终端是🍎 macOS Ventura 13.4.1(c),Windows系统环境构建方式大同小异) Basic build tools (brew management recommended)(基础构建工具(推荐brew管理))123456cmakewgetgitrustprotobufpython3.x Project key directory(项目关键目录) stable-diffusion-webui/extensions (扩展) stable-diffusion-webui/models (模型) Construction steps(构建步骤) Install and start service: stable-diffusion-webui (源码安装:stable-diffusion-webui) 12345678# Pull source codegit clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git && cd stable-diffusion-webui# start web UI (启动web UI)./webui.sh# Running on local URL: http://127.0.0.1:7860 Default web UI url: http://127.0.0.1:7860 base model source download (绘图基础模型下载) AI drawing basic model download 1234567# models directorycd stable-diffusion-webui/models/Stable-diffusionwget https://huggingface.co/stabilityai/stable-diffusion-2/resolve/main/768-v-ema.ckpt# back stable-diffusion-webui & restart webui.sh./webui.sh Basic extensions install (基础插件安装) Install controlnet extension (安装ContolNet扩展)12345678# cd extensions pathcd stable-diffusion-webui/extensions# Pull extension source codegit clone https://github.com/Mikubill/sd-webui-controlnet.git# back to browser web UI click button:apply and restart Project key directory(项目关键目录) stable-diffusion-webui/extensions (扩展) stable-diffusion-webui/models (模型) Install openpose-editor extension (Custom pose) (安装openpose扩展) 1234567# cd extensions pathcd stable-diffusion-webui/extensions# Pull extension source codegit clone https://github.com/fkunn1326/openpose-editor.git# back to browser web UI click button:apply and restart Extensions include directory structure (扩展包含目录结构)1234extensions├── openpose-editor-master├── put extensions here.txt└── sd-webui-controlnet-main Basic Extensions have been installed. back home page and open ControlNet tab. Controlnet associated base model download (controlnet相关联的基础模型下载)A list of optional models is suggested123456789101112# cd models ControlNet pathmkdir -p stable-diffusion-webui/models/ControlNet && cd stable-diffusion-webui/models/ControlNet# cannywget https://huggingface.co/lllyasviel/ControlNet/resolve/main/models/control_sd15_canny.pth# openposewget https://huggingface.co/lllyasviel/ControlNet/resolve/main/models/control_sd15_openpose.pth# scribblewget https://huggingface.co/lllyasviel/ControlNet/resolve/main/models/control_sd15_scribble.pth Models include directory structure (模型包含目录结构)12345678models├── ControlNet│ ├── control_sd15_canny.pth│ ├── control_sd15_openpose.pth│ └── control_sd15_scribble.pth├── Stable-diffusion│ ├── 768-v-ema.ckpt│ └── Put Stable Diffusion checkpoints here.txt Installation completeNotice:Note that some source code, model and extension download network is slow, it is recommended to use professional download tools to download(注意事项,部分源码、模型和扩展下载网络缓慢,建议采用专业下载工具下载)","link":"/4de059e7.html"},{"title":"常用GUI库","text":"常用GUI库X协议 X Window System(X11),第11个版本。 下一代改进协议Wayland,Wayland不仅仅是要完全取代X11,取代目前Linux桌面上X Client/X Server的设计理念。 注意事项:截至2020年大多数用于Linux的视频游戏和图形密集型应用程序仍为X11编写。但许多封闭源代码的图形驱动程序,例NVIDIA GPU的驱动程序都尚未完全提供对Wayland的支持。 X 协议由 X server 和 X client 组成: X server 管理主机上与显示相关的硬件设备,它负责屏幕画面的绘制与显示,以及将输入设备的动作告知 X client。 X client 应用程序端则主要负责事件的处理(程序的逻辑)。 Linux/Unix类操作系统上, $DISPLAY设置图形显示出处. graph LR A[X clients]--->B[Xlib来封装协议]; B--->C[X server]; C--->D[QT] C--->E[GTK] X clients 了Xlib来封装协议;Xlib不够方便,于是就有了qt和gtk,提供了很多窗口控件(widgets) X和XFree86 XFree86基于X协议实现免费X服务器软件 X Window System(X11),第11个版本 X11R6 实际上是 X Protocol version 11 Release 6(X协议第11版第六次发行) X和XFree86: graph TD A[X协议]--->B[免费] A[X协议]--->C[商用] B--->D[xorg] B--->E[Xfree86] B--->F[Wayland] C--->G[MOTIF] XFree86只是实现X协议的一个免费X服务器软件.商业上常用MOTIF,现在还有XORG","link":"/8ee4d6e3.html"},{"title":"clang io format","text":"输入输出格式化终端输入 input键盘获取输入(三个函数): scanf():和 printf() 类似,scanf() 可以输入多种类型的数据。 getchar()、getche()、getch():这三个函数都用于输入单个字符。 gets():获取一行数据,并作为字符串处理。 scanf()默认以空格分割: scanf() 在读取数据时需要的是数据的地址,字符串名字或者数组名字在使用的过程中自动会转换为内存地址,所以无需加& int、char、float 等类型的变量用于 scanf() 时都要在前面添加&,而数组或者字符串用于 scanf() 时不用添加&,它们本身就会转换为地址。 scanf() 可以读取带空格的字符串,字符的数目,指定的字符,不读取某些字符,丢弃字符。 终端输出 output三个函数可以用来在显示器终端输出数据: puts():仅输出字符串,并且输出结束后会自动换行 putchar():仅输出单个字符 printf():可以输出各种类型的数据 printf()缓存机制printf() 输出延迟问题: 12345678printf("输出1");//sleep() 是 Linux 和 Mac OS 下特有的函数,Sleep()是Windows函数sleep(2); // 延迟2sprintf("输出2"); 本质上printf() 执行结束以后数据并没有直接输出到显示器上,而是放入了缓冲区,输出缓冲区直到遇见换行符\\n才将缓冲区中的数据输出到显示器上(Linux 或者 Mac OS 下运行)对缓存的理解,是处理C语言各种疑难问题的重要思路和方向。","link":"/5fc261d7.html"},{"title":"clang Data Type","text":"clang Data TypeC语言’\\0’的含义 \\0 是判定字符数组结束的标识 \\0 表示的是ASCII控制字符中空字符的含义,代码为NUL,非NULL \\0 本身占一个位置 \\0 在数组中占有空间但不显性 NUL和NULL的区别 NUL 是ASCII 字符集中 ‘\\0’ 字符的名字,它的字节模式为全 0。NULL 指一个其值为 0 的指针。它们都是整型值,其值也相同,所以它们可以互换使用。 符号 NULL 在头文件 stdio.h 中定义。另一方面,并不存在预定义的符号 NUL。 NULL 指针并不指向任何对象。除非是用于赋值或比较运算,出于其他任何目的的使用NULL指针都是非法的。 NULL是一个宏,它在几个标准头文件中定义,0是一个整型常量,’\\0’是一个字符常量,而NUL是一个字符常量的名字。术语都不可互换。 1、NULL就是空指针 2、0可以被用于任何地方,它是表示各种类型零值的符号并且编译器会挑出它 3、’\\0’应该只被用于结束字符串 4、NUL没有被定义于C和C++,它不应该被使用,除非你自己定义它,像:#define nul ‘\\0’ 空指针的用法 : 用空指针终止对递归数据结构的间接引用 用空指针作函数调用失败时的返回值 用空指针作警戒值 加减乘除运算简写方式: 1234int a = 1, b = 2;a += 1; // a = a + 1;a *= (b-1); // a = a * (b-1);a -= (a+2); // a = a - (a+2); 特殊简写(自加或自增: ++ 和 – 自增运算符和自减运算符) 12345// a = a + 1a++;// a = a + 1++a; 前自增和后自增区别: ++ 在前面叫做前自增 ++ 在后面叫做后自增 – 在前面叫做前自减 – 在后面叫做后自减1234567891011121314int a = 1, b = 2;int a1 = ++a, b1 = b++; printf("a=%d, a1=%d\\n", a, a1);// 注意事项:b1=b++,b 值先赋值 b1,然后再加 1。printf("b=%d, b1=%d\\n", b, b1);//综合操作int a = 2, b = 1;int c = a - (b--); // 后自减,会先进行a-b运算,结果是 1,然后 b 再自减,就变成了 0;最后再将a-b的结果(也就是1)交给 c,所以 c 的值是 1。int d = (++a) - (--b); //b 的值已经变成 0。对于d=(++a)-(--b),a 会先自增,变成 3,然后 b 再自减,变成 -1,最后再计算3-(-1),结果是 4,交给 d,所以 d 最终是 4。printf("c=%d, d=%d\\n", c, d); 注意事项: 1.C语言中的除法运算,类型注意事项: **当除数和被除数都是整数时,运算结果也是整数;非整除则直接丢掉小数部分只保留整数部分,与小数赋值给整数类型同理。 除数和被除数中如含有小数,那么运算结果也是小数,double 类型小数。 2.取余注意事项: C语言中的取余运算 % 的两边都必须是整数,小数非法,否则编译器报错。余数可以是正数也可以是负数,由 % 左边的整数决定:如果 % 左边是正数,那么余数也是正数;如果 % 左边是负数,那么余数也是负数","link":"/8ed5dc39.html"},{"title":"clang macro","text":"C Macro 宏定义#define 宏定义命令,C语言预处理命令。标识符来表示一个字符串,代码运行中会将表示符进行全部替换成指定的字符串。 1234567#define N 1int main(){ int sum = 1 + N; printf("Output: %d\\n", sum); return 0;}// output: 2 宏定义和定义全局变量的区别和注意事项 作用时间不同:宏定义在编译期间即会使用并替换,而全局变量要到运行时才可以。 本质类型不同: 宏定义的只是一段字符,在编译的时候被替换到引用的位置。在运行中是没有宏定义的概念的。而变量在运行时要为其分配内存。 宏定义不可以被赋值,即其值一旦定义不可修改,而变量在运行过程中可以被修改。 宏定义只有在定义所在文件,或引用所在文件的其它文件中使用。全局变量可以在工程所有文件中使用,只需在使用前加一个声明就可以,即宏定义不支持extern模式。","link":"/c603c446.html"},{"title":"clang ANSI lib 标准差异汇总速查","text":"C(ANSI C)语言标准函数库C标准库概述基本说明从语言本身的角度(与平台无关)来说,标准C语言(ANSI C)共定义了15 个头文件,截至C11标准共包含29个头文件。 各标准差异: 标准名称 头文件差异 C89 15 标准头文件 C90、C89 标准头文件无差异, 排版存在差异 C95 +3 标准头文件 C99 +6 标准头文件 C11 +5 标准头文件 C17 无 C标准库按使用频度:常用: 一组: 1234stdio.hctype.hstdlib.hstring.h 二组: 1234assert.hlimits.hstddef.htime.h 三组: 1234567float.hmath.herror.hlocale.hsetjmp.hsignal.hstdarg.h 标准库备注 头文件 标准版本 备注 assert.h C89/C90 条件编译宏,将参数与零比较 ctype.h C89/C90 用于确定包含字符数据中的类型 errno.h C89/C90 报告错误条件宏,内含3个宏(EDOM 特定含义的错误,在math.h 中表示域错误;ERANGE 特定含义的错误,在math.h 中表示溢出错误;errno 库函数中用来盛放错误代码的宏) float.h C89/C90 浮点数类型,提供范围和精度的宏,包含了一组与浮点值相关的依赖于平台的常量 limits.h C89/C90 检测整型数据数据类型的表达值范围 locale.h C89/C90 本地化 math.h C89/C90 常用数学函数库 setjmp.h C89/C90 非局部跳转 signal.h C89/C90 信号处理 stdarg.h C89/C90 可变参数 stddef.h C89/C90 常用宏定义 stdio.h C89/C90 输入/输出 stdlib.h C89/C90 standard library标准库函数库:内存管理、程序工具、字符串转换、随机数 string.h C89/C90 字符串处理 time.h C89/C90 时间处理 wchar.h C95 扩展多字节和宽字符处理 wctype.h C95 包含了一系列用于检测和转换单个宽字符的函数库,wctype.h 是ctype.h的宽字符版本,wctype.h的出现晚于ctype.h。wctype.h的引入使C语言可以更好地处理英文以外的语言。 complex.h C99 复数运算 fenv.h C99 浮点数环境 inttypes.h C99 整数类型的格式转换 stdbool.h C99 布尔类型 stdint.h C99 定宽整数类型 tgmath.h C99 泛型数学(包装 math.h 和 complex.h 的宏) stdalign.h C11 alignas 与 alignof 便利宏 stdatomic.h C11 原子类型 stdnoreturn.h C11 noreturn 便利宏 threads.h C11 线程库 uchar.h C11 UTF-16 和 UTF-32 字符工具 运行时库C run-time library(CRT) C运行时库区别于C++语言的运行时库,指的是C程序运行时需要调用的库的函数,是一个相对概念 C运行时库由编译器生产商提供,亦称为第三方 C 运行库(Third party C run-time libraries) C运行时库一般是平台或系统提供,windows或linux,macos等。 Universal C Runtime 库(UCRT 库)通用C运行时库,包含多C库的头文件,Windows组件之一,自win10开始以系统发行方式部分提供。关联库: 对应的lib库为libucrt.lib 对应的dll库为ucrtbase.dll UCRT库文件: 库 关联的DLL 备注 选项 预处理器指令 libucrt.lib 无 将 UCRT 静态链接到你的代码。 /MT _MT libucrtd.lib 无 用于静态链接的 UCRT 调试版本。不可再发行。 /MTd _DEBUG,_MT ucrt.lib ucrtbase.dll UCRT 的 DLL 导入库。 /MD _MT,_DLL ucrtd.lib ucrtbased.dll UCRT 调试版本的 DLL 导入库。不可再发行。 /MDd _DEBUG,_MT,_DLL 标准库和运行时库的区别 C标准库再跨平台系统上,执行结果一致 C运行库是C标准库的扩展集,完全包含C标准库,但扩展的函数因不同的操作系统平台有差异 不同的操作系统,c运行时库执行的结果可能不同,但是对c标准库的支持是完全一致","link":"/f4ab9929.html"},{"title":"WDFT (Warped Discrete Fourier Transform)","text":"WDFT (Warped Discrete Fourier Transform) by GoImplementation of Go language: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980package mainimport ( "fmt" "math" "math/cmplx")// 定义扭曲函数,这里以幂函数为例func distortionFunction(omega float64) float64 { return math.Pow(omega, 1.5) // 可根据需要修改扭曲函数}// 离散傅里叶变换func dft(signal []float64) []complex128 { N := len(signal) result := make([]complex128, N) for k := 0; k < N; k++ { var sum complex128 for n := 0; n < N; n++ { omega := -2 * math.Pi * float64(k*n) / float64(N) sum += complex(signal[n], 0) * cmplx.Exp(complex(0, omega)) } result[k] = sum } return result}// 扭曲离散傅里叶变换func wdft(signal []float64) []complex128 { N := len(signal) spectrum := dft(signal) for k := 0; k < N; k++ { omega := 2 * math.Pi * float64(k) / float64(N) warpedOmega := distortionFunction(omega) spectrum[k] *= cmplx.Exp(complex(0, warpedOmega)) } return spectrum}// 反离散傅里叶变换func idft(spectrum []complex128) []float64 { N := len(spectrum) result := make([]float64, N) for n := 0; n < N; n++ { var sum complex128 for k := 0; k < N; k++ { omega := 2 * math.Pi * float64(k*n) / float64(N) sum += spectrum[k] * cmplx.Exp(complex(0, omega)) } result[n] = real(sum) / float64(N) } return result}func main() { // 生成一个简单的示例信号 signal := make([]float64, 8) for i := range signal { signal[i] = float64(i) } // 进行WDFT变换 spectrum := wdft(signal) // 对频域表示进行处理(这里省略具体处理步骤) // 进行反离散傅里叶变换 outputSignal := idft(spectrum) // 输出结果 fmt.Println("原始信号:", signal) fmt.Println("经过WDFT变换后的信号:", outputSignal)} Implementation of Rust language:Cargo.toml 12[dependencies]num = "0.4" 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576use std::f64::consts::PI;use num::complex::Complex;// 定义扭曲函数fn distortion_function(omega: f64) -> f64 { omega.powf(1.5) // 可根据需要修改扭曲函数}// 离散傅里叶变换fn dft(signal: &[f64]) -> Vec<Complex<f64>> { let n = signal.len(); let mut spectrum = vec![Complex::new(0.0, 0.0); n]; for k in 0..n { let mut sum = Complex::new(0.0, 0.0); for n in 0..n { let omega = -2.0 * PI * k as f64 * n as f64 / n as f64; sum += Complex::new(signal[n], 0.0) * Complex::from_polar(1.0, omega); } spectrum[k] = sum; } spectrum}// 扭曲离散傅里叶变换fn wdft(signal: &[f64]) -> Vec<Complex<f64>> { let n = signal.len(); let spectrum = dft(signal); let warped_spectrum: Vec<Complex<f64>> = spectrum .iter() .enumerate() .map(|(k, &value)| { let omega = 2.0 * PI * k as f64 / n as f64; let warped_omega = distortion_function(omega); value * Complex::from_polar(1.0, warped_omega) }) .collect(); warped_spectrum}// 反离散傅里叶变换fn idft(spectrum: &[Complex<f64>]) -> Vec<f64> { let n = spectrum.len(); let mut signal = vec![0.0; n]; for n in 0..n { let mut sum = Complex::new(0.0, 0.0); for k in 0..n { let omega = 2.0 * PI * k as f64 * n as f64 / n as f64; sum += spectrum[k] * Complex::from_polar(1.0, omega); } signal[n] = sum.re / n as f64; } signal}fn main() { // 生成一个简单的示例信号 let signal: Vec<f64> = (0..8).map(|i| i as f64).collect(); // 进行WDFT变换 let spectrum = wdft(&signal); // 对频域表示进行处理(这里省略具体处理步骤) // 进行反离散傅里叶变换 let output_signal = idft(&spectrum); // 输出结果 println!("原始信号:{:?}", signal); println!("经过WDFT变换后的信号:{:?}", output_signal);}","link":"/e324f38b.html"},{"title":"Eight Fallacies of Distributed Systems (分布式八大谬论)","text":"Eight Fallacies of Distributed SystemsThe network is reliable网络可靠。 Latency is zero延迟为零。 Bandwidth is infinite带宽是无限的。 The network is secure网络是安全的。 Topology doesn’t change拓扑不会改变。 There is one administrator只有一个管理员。 Transport cost is zero运输成本为零。 The network is homogeneous网络是同质的。","link":"/67fb071a.html"},{"title":"MySQL 8.0为什么使用utf8mb4_0900_ai_ci默认校对规则,而不使用utf8mb4_general_ci?","text":"MySQL 8.0 选择 utf8mb4_0900_ai_ci作为默认校对规则原因 主要的考虑主要基于对全球化支持的增强,基于Unicode 9.0规范,utf8mb4_0900_ai_ci在未来可以更容易地适应新的Unicode规范和扩展字符集。 更精确的字符处理以及适应现代应用需求等方面。 两者差异对比要点: 全球化支持的增强 更广泛的字符集支持:utf8mb4_0900_ai_ci支持Unicode 9.0标准,这意味着它可以存储和处理更多的字符,包括许多特殊的emoji表情和其他少见字符。这对于现代应用程序尤为重要,因为它们常常需要处理这些扩展字符集。 多语言环境的适用性:随着全球化的发展,应用程序需要支持多种语言和字符集。utf8mb4_0900_ai_ci不仅支持更多的语言和字符,还能更准确地处理这些语言中的特定字符问题。 国际化应用的优选:在涉及多语言和国际化处理的应用中,utf8mb4_0900_ai_ci能够提供更全面的支持,确保数据的准确性和一致性。 更精确的字符处理 不区分重音和大小写:与utf8mb4_general_ci相比,utf8mb4_0900_ai_ci在比较和排序字符时不区分重音和大小写。例如,‘é’和‘e’被认为是相同的字符,‘A’和‘a’也被认为是相同的字符。这种规则对于处理语言如西班牙语和法语等重音丰富的语言尤为重要。 基于Unicode 9.0的排序和比较规则:通过实现Unicode 9.0的排序和比较规则,utf8mb4_0900_ai_ci提供了更精确、更现代的Unicode支持。这确保了在数据库中对字符进行排序和比较时能够按照最新的国际化标准进行。 提升搜索和排序的准确性:由于其先进的排序规则,utf8mb4_0900_ai_ci能够更准确地处理涉及重音符号的字符排序,这在许多语言中是必需的。 适应现代应用需求 支持最新Unicode规范:Unicode规范不断更新,以包含更多的字符和修正现有的规则。utf8mb4_0900_ai_ci基于较新的Unicode 9.0规范,能够更好地适应未来的应用需求。 提高数据准确性:在需要高度准确的字符表示和处理的场景中,utf8mb4_0900_ai_ci能够提供更好的支持。例如,电子商务平台和内容管理系统等需要处理多语言字符并保持数据准确性的应用,都会从中受益。 满足多样化的使用场景:无论是国际化应用还是本地化要求高的应用,utf8mb4_0900_ai_ci都能提供强大的支持,满足多样化的使用场景。 性能与优化 性能的权衡考虑:虽然utf8mb4_0900_ai_ci在处理更复杂的排序和比较规则时可能会牺牲一定的性能,但这与其提供的其他优势相比是值得的。尤其是在现代硬件条件下,这种性能差异的影响越来越小。 优化字符存储和传输:通过支持更多的字符集,utf8mb4_0900_ai_ci能够在存储和传输数据时更加高效。特别是在处理Emoji表情和其他4字节字符时,其优势尤为明显。 适应高负载应用环境:在高负载和高并发的应用环境中,utf8mb4_0900_ai_ci能够保持较好的性能表现,同时确保数据的一致性和准确性。 兼容性与扩展性 向下兼容早期版本:尽管utf8mb4_0900_ai_ci是为MySQL 8.0及以上版本设计的,但它也在一定程度上保持了对早期版本的兼容。这使得升级数据库时能够更加平滑地过渡。 未来扩展的可能性:基于Unicode 9.0规范,utf8mb4_0900_ai_ci在未来可以更容易地适应新的Unicode规范和扩展字符集。这对于确保数据库系统在未来继续有效运行至关重要。 跨平台和跨系统的支持:由于其强大的兼容性和扩展性,utf8mb4_0900_ai_ci可以在各种平台和系统中使用,确保了广泛的应用范围。 概述MySQL 8.0采用utf8mb4_0900_ai_ci作为默认校对规则,主要是为了更好地适应全球化应用需求、提供更精确的字符处理能力、并确保数据库系统在未来的持续可用性和扩展性。尽管在性能上可能稍有牺牲(实际上经过mysql8.0版本的重构,性能损失可以不必过度考量),但其带来的长期收益和对现代应用需求的支持使得这一选择具有显著的合理性和前瞻性。","link":"/93d6d12a.html"},{"title":"GitHub以及其他GIT平台中启用GPG2认证基本使用流程(MacOS),增强身份识别和安全性","text":"base gnupg(version >= 2.1.17,版本gnupg已包含gpg-agent)注意事项:gpg2默认交互式输入密码,有相应的解决方案。 brew install(推荐):1brew install gnupg 版本信息(截至2022.06.19)1234567gnupg: stable 2.3.6 (bottled)GNU Pretty Good Privacy (PGP) packagehttps://gnupg.org//usr/local/Cellar/gnupg/2.3.6 (149 files, 13.3MB) * Poured from bottle on 2022-05-04 at 00:14:15From: https://mirrors.ustc.edu.cn/homebrew-core.git/Formula/gnupg.rbLicense: GPL-3.0-or-later 生成以及查看密钥 生成密钥(交互选择建议默认) 1gpg --full-generate-key 在提示时,指定要生成的密钥类型,或按 Enter 键接受默认值。 在提示时,指定想要的密钥大小,或按 Enter 键接受默认值。 密钥必须至少是 4096 位。 输入密钥的有效时长。 按 Enter 键将指定默认选择,表示该密钥不会过期。 验证您的选择是否正确。 输入您的用户 ID 信息。 查看已签发密钥 1gpg --list-secret-keys --keyid-format=long 查看指定公钥的信息(Prints the GPG key ID, in ASCII armor format) 1gpg --armor --export <GPG key ID> 复制公钥信息到GitHub上:从 -----BEGIN PGP PUBLIC KEY BLOCK----- 开始,到 -----END PGP PUBLIC KEY BLOCK----- 设置邮箱(建议全局默认一个常用Email): 1git config --global user.email "" 设置项目开启GPG验证签名(不建议全局开启,可局部开启,防止影响其他平台或项目的提交引发连锁反应) 1git config commit.gpgsign true GPG密钥导出以及备份创建导出备份密钥文件的路径(例如): 12# 注意:密钥备份完毕后建议清理此目录及文件夹!mkdir -p ~/GPGBAK 警告:导出的备份密钥为敏感文件,为了安全请确保密钥异地保存妥当后,清理导出当前的备份文件 备份GPG公钥 1gpg -o ~/GPGBAK/gpg_keys_github_macos --export <GPG Key ID> 备份GPG私钥 1gpg -o ~/GPGBAK/gpg_secret_keys_github_macos --export-secret-keys <GPG Key ID> 常见问题 在终端可能出现git提交commit时提交失败需要输入GPG密码解密密钥? 可设置终端信息,然后重新开启一个终端生效。 错误信息: 12error: gpg 数据签名失败fatal: 写提交对象失败 解决方案: 1vim ~/.zshrc 12# GPG CONFIG (交互式窗口不弹出解决方案)export GPG_TTY=$(tty) GPG2密码缓存时间设置:默认文件不存在则创建 123456789touch ~/.gnupg/gpg-agent.conf``` **推荐**配置gpg-agent 选项(密码缓存有效时间(不建议ttl设置过长!) * GnuPG agent是一个帮助工具,当你运行gpg用于缓存私钥时会自动运行。* default-cache-ttl(seconds):如果在失效期前,使用了相同名称的私钥,那么计数器会被重置,默认是600s(10min)* max-cache-ttl (seconds):不论你最近是否使用过私钥,只要超过了此值,就需要进行重新验证,默认是30min。* **可设置长时间,但不建议太长**,还有一种是定期刷新有效时间,但需要配置系统任务容易遗忘所以不推荐。 default-cache-ttl 1800max-cache-ttl 7200 12重启 gpg-agent进程: echo RELOADAGENT | gpg-connect-agent 提交推送完成后GitHub仍然提示未验证?解决方案:检查本地提交的GIT默认邮箱和GitHub平台的登记邮箱是否一致,不一致可修改当前项目的邮箱保持和GPG一致即可。 其他平台如何设置?解决方案:其他GIT在线平台和GitHub操作方法基本一致。 请妥善保存和使用GPG签名密钥,防止敏感文件泄漏!","link":"/eadfec01.html"},{"title":"JavaScript map function grammatical sugar trap","text":"Don’t pursue techniques that seem too fancy, or they may backfire(不要追求看似过于花哨的技巧,否则可能适得其反) 12let m = [10, 10, 10].map(parseInt);document.write(m);","link":"/ad4a4750.html"},{"title":"Go tool pprof性能监控调试工具基本使用说明","text":"Go tool pprof使用方式go中有pprof包来做代码的性能监控主要涉及两个pkg: 1234567891011#web服务器:import ( "net/http" _ "net/http/pprof")#一般应用程序(实际应用无web交互)import ( "net/http" _ "runtime/pprof") net/http/pprof中只是使用runtime/pprof包来进行封装了一下,并在http端口上暴露出来。 Go tool pprof辅助工具安装(图形工具graphviz为例) __Windows__:1.官方下载安装包: http://www.graphviz.org/download/下载Stable稳定版本(.msi)2.配置PATH系统环境变量:C:\\Program Files (x86)\\Graphviz2.38\\bin Linux(例:Centos) 方式1).添加repo依赖http://204.178.9.49/graphviz-rhel.repo 123yum list available 'graphviz*'yum install 'graphviz*' --skip-broken#备注:--skip-broken可选:跳过错误依赖,不加这个参数会提示安装包依赖错误,因为这里并不需要其它的安装包,所以跳过即可。 –skip-broken可选:跳过错误依赖,不加这个参数会提示安装包依赖错误,因为这里并不需要其它的安装包,所以跳过即可。 方式2).源码包编译安装./configuremakemake install MacOS:brew install graphviz Go tool pprof常用基本调试基本命令(默认30s采集时间,可通过–seconds)HTTP场景(参数可选:–text):Heap profile: 1go tool pprof --text http://localhost:8080/debug/pprof/heap CPU profile: 1go tool pprof --text http://localhost:8080/debug/pprof/profile Goroutine blocking profile: 1go tool pprof --text http://localhost:8080/debug/pprof/block 1.实时通过地址查看浏览器: http://localhost:8080/debug/pprof/;2.通过生成的profile文件分析;选择指定的profile压缩gz文件(.gz),使用go tool pprof进入 12345go tool pprof http://localhost:8080/debug/pprof/profile#结束后直接进入交互:(pprof) web(pprof) 如查看历史调试文件信息,通过指定的profile文件进入即可:go tool pprof [*.gz] pprof交互基本命令:web 直接生成web浏览器可访问的svg图;(其他命令自行摸索)Windows下自动生成.svg文件且调用默认浏览器访问;MacOS下自动生成.gz文件,系统限制可根据提示文件路径通过手动访问查看; 【注意事项】:profile文件为空的问题, heap和block一般不受影响。执行交互web命令会报: 123(pprof) webprofile is empty(pprof) 产生原因:pprof内存分析器采取抽样的方式,它仅仅从一些内存分配的子集中收集信息。有可能对一个对象的采样与被采样对象的大小成比例。通过使用go test –memprofilerate标识,或者通过程序启动时 的运行配置中的MemProfileRate变量来改变调整这个采样的比例。如果比例为1,则会导致全部申请的信息都会被收集,但是这样的话将会使得执行变慢。默认的采样比例是每512KB的内存申请就采样一次。 方法1).在进行调试时,指定运行参数,或运行代码中动态调整参数1go tool pprof --text http://localhost:8080/debug/pprof/profile 此命令将会打印耗费最多CPU时间的函数列表。这里有几种可用的输出形式,最实用的有 –text, –web 和 –list。运行 “go tool pprof” 来得到完整的列表。 【备注】:实际测试时,MacOS下基本是空的,需要指定参数。 方法2).设置环境变量(此方法极不推荐!)设置Go环境变量 GODEBUG=”memprofilerate=1”. 通过控制采样的比例和行为,可以达到性能调试粒度的控制!","link":"/2188b831.html"},{"title":"Go:方法值(func value) 和 方法表达式(func expression)","text":"方法值(func value) & 方法表达式(func expression)依据函数或方法具备两大特点: 1.函数本身是一种类型T; 2.函数变量:函数或方法本身储存在变量中; 方法值方法值的本质是调用时隐藏了接收者,和传统调用是等价的; 12345678910111213141516171819202122232425262728package mainimport "fmt"type A struct { name string}func (a *A) SetValue () { fmt.Println("set")}func main() { aa := A{"jack"} //传统调用 aa.SetValue() //方法值,调用时隐藏接收者 vFunc := aa.SetValue vFunc() //方法表达式,调用时隐藏接收者 aFunc := (*A).SetValue //显式传递接收者,等价于aa.SetValue() aFunc(&aa)}","link":"/78f4f0b0.html"},{"title":"Go:chain operation","text":"chain operation链式调用注意事项 本身为较宽泛的概念 链式调用的场景: 返回值是一个函数或方法(很少有实际意义); 方法链(func chain或method chain):返回值是一个对象时,可以直接调用对象绑定的方法; 链式调用方法链是包含关系,严格意义上说,链式调用 ≠ 方法链; 链式调用的优点 调用过程更接近自然语言,链式呈现可读性好; 参数列表复杂化的方法极大简化清晰; 精简代码量,避免主操作对象反复的书写; 优势:设计上,操作与数据分离、解耦; 链式调用的缺点 开发者需要记住调用的层数,层数不能过多。 每次调用都需要创建很深的调用堆栈,效率相对较低。 链式操作的实质(函数OR方法)操作 =》 返回对象 =》继续操作返回对象所属函数OR方法 12345678910111213141516171819202122232425262728package mainimport "fmt"type A struct { Aa string Ab int}func (p *A) SetAa(aa string) *A { p.Aa = aa return p //返回操作对象}func (p *A) SetAb(ab int) *A { p.Ab = ab return p //返回操作对象}func (p *A) Print() { fmt.Printf("Aa:%s || Ab:%d\\n", p.Aa, p.Ab)}func main() { varA := &A{} varA.SetAa("Aa").SetAb(100).Print()}","link":"/b45ac9b7.html"},{"title":"Go:func 函数","text":"func 函数func函数(适用于method)小结Go函数数也是一种类型,可以和其他类型一样被保存在变量中。和接口一样,接口也是一种类型。 12345678910111213package mainimport ( "fmt")func foo() { fmt.Println("foo")}func main() { var f func() f = foo f()} Go函数类型实现接口——把函数作为接口来调用函数体实现接口函数的声明不能直接实现接口,需要将函数定义为类型后,使用类型实现结构体。当类型方法被调用时,还需要调用函数本体。 1234567891011121314// 函数定义为类型type FuncCaller func(interface{}) // func(interface{}) 定义为 FuncCaller 类型。// 实现Invoker的Callfunc (f FuncCaller) Call(p interface{}) { // 调用f()函数本体 f(p) //FuncCaller 的 Call() 方法将实现 Invoker 的 Call() 方法。 // FuncCaller 的 Call() 方法被调用与 func(interface{}) 无关,还需要手动调用函数本体。}//代码备注://以上函数类型,需要函数本身进行逻辑处理。FuncCaller 无须被实例化,只需要将函数转//换为 FuncCaller 类型即可,函数来源可以是命名函数、匿名函数或闭包。 HTTP实现场景:函数 handler() 转为 HandlerFunc 类型,HandlerFunc 类型实现了 Handler 的 ServeHTTP 方法,底层可以同时使用各种类型来实现 Handler 接口进行处理。 1234567891011121314151617181920212223HTTP 包中包含有 Handler 接口定义,代码如下:type Handler interface { ServeHTTP(ResponseWriter, *Request)}Handler 用于定义每个 HTTP 的请求和响应的处理过程。同时,也可以使用处理函数实现接口,定义如下:type HandlerFunc func(ResponseWriter, *Request)func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r)}要使用闭包实现默认的 HTTP 请求处理,可以使用 http.HandleFunc() 函数,函数定义如下:func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { DefaultServeMux.HandleFunc(pattern, handler)}而 DefaultServeMux 是 ServeMux 结构,拥有 HandleFunc() 方法,定义如下:func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { mux.Handle(pattern, HandlerFunc(handler))}上面代码将外部传入的函数 handler() 转为 HandlerFunc 类型,HandlerFunc 类型实现了 Handler 的 ServeHTTP 方法, 底层可以同时使用各种类型来实现 Handler 接口进行处理。 Go可变参数函数调用注意事项(three dots) 若将 string 数组切片,每项独自传入函数,则会执行[]T{arg1,arg2}等类似操作,从新进行初始化; 若将 interface{} 数组切片打散后直接传入函数,则不再进行对象的创建,直接试用该对象; Go … three dots 用法:变长的函数参数(逐一传参用法)调用参数最后一个…T,在参数列表的最后使用若干个类型为T的参数。…T在函数内部的类型实际是[]T. 调用拥有变长参数列表的函数slice类型参数不必拆分调用,直接在slice后跟… 标识数组元素个数例如[…]int{1,2,3} Go命令行中的通配符描述包文件的通配符。会执行当前目录和所有子目录的所有包: 12345go test ./...go run ./...go build ./..","link":"/4f443298.html"},{"title":"Proverbs from @rob_pike's inspiring talk at Gopherfest SV 2015 (video)","text":"Go Proverbs Simple, Poetic, Pithy Don't communicate by sharing memory, share memory by communicating. Concurrency is not parallelism. Channels orchestrate; mutexes serialize. The bigger the interface, the weaker the abstraction. Make the zero value useful. interface{} says nothing. Gofmt's style is no one's favorite, yet gofmt is everyone's favorite. A little copying is better than a little dependency. Syscall must always be guarded with build tags. Cgo must always be guarded with build tags. Cgo is not Go. With the unsafe package there are no guarantees. Clear is better than clever. Reflection is never clear. Errors are values. Don't just check errors, handle them gracefully. Design the architecture, name the components, document the details. Documentation is for users. Don't panic. Proverbs from @rob_pike's inspiring talk at Gopherfest SV 2015 (video). The Gopher character is based on the Go mascot designed by Renée French and copyrighted under the Creative Commons Attribution 3.0 license. These proverbs are the basis of a talk by Rob Pike and the list may be updated when he next gives the talk. Please read the contribution guidelines before opening an issue to nominate a new proverb.","link":"/5978836a.html"},{"title":"Jack Liu Golang personal summary combing notes","text":"Jack Liu Golang personal summary combing notesJack Liu Golang personal summary notes GoJack Liu contact Item Contact Author Jack Liu Email ljqlab@163.com WeChat laulinux QQ 404691073 Blog https://www.wdft.com I love Go,Simple, efficient, practical, engineered …The world of programming should be pluralistic, free from any one mindset.EN English DocumentsEnglish Documents zh_CN 中文README_CN","link":"/5767103d.html"},{"title":"Go:goroutine","text":"goroutineGolang不使用OS层process而使用语言层面(Goroutine)处理 并发 & 并行 Task任务方案(针对业务来说)的个人思考和实践思路随想 —Jack Liu 秋1.使用OS层面进程管理,虽然成本低廉快捷,但对CPU的性能开销比较大,Golang通过Goroutine的引入,构建一种SandBox沙箱容器式的方案,可以将并发处理任务放在语言层面内部,“隔离“在系统层面之上,构建Goroutine池的同时,也能保证在性能可靠的前提下,安全性也增强。 目前大规模分布式系统的整体方向,大部分也都是建立在OS系统层之上(而非系统层面)以达到可控的标准控制,将OS系统级内核CPU的开销降到最低保证OS层流畅运行,这也让Linux为代表的服务器OS系统更“专注”做Base底层基础性的业务支撑。 2.系统层面上,抛开编程语言层面不谈,服务端越来越趋于Service服务化和分布式、集群化,以此应对越来越复杂的业务。现有编程语言历史遗留和生态环境等因素处理的成本较高,针对多核CPU使用率也不高,性能问题凸显。Golang在服务器端的优势在于,非常低成本将开发人员从以前的单进程类编程语言中解放,提供最低成本快速转变为并行编程的思维模式。Goroutine并发执行的模式,不放在系统进程处理,好处:(1).安全隔离型设计,限制进程中Task Process处理的边界,在大规模集群服务器中使用相对统一的标准处理方式,最大限度规避OS层面的差异带来的问题;(2).降低OS进程的开销,不因golang的执行导致拖累系统CPU资源;(3).并发Task任务行为和状态可控,内存占用开销小,容量自由扩展;(4).轻量级在协程处理时可靠性高;(5).使用这种机制,可以较低成本构建大型和可伸缩计算和批处理Task任务的应用和程序,一开始Golang的定位就是系统级编程语言,所以二进制的运行性能不会差,现阶段的语言性能之争毫无意义。 目前业内针对业务处理的大型系统应用的常态应该至少包含两点:1.支持最小成本组织大规模数据和计算处理;2.Task任务的行为和状态能够可靠、低成本可控。 云计算追求对服务端在安全可控的前提下软硬件资源的最低成本配置和最佳的资源调度,做的所有分布式、自由伸缩、集群的重要原因也是源为此,Goroutines在这方面大有可为。 官方一句话说得比较直白和代表性:Do not communicate by sharing memory; instead, share memory by communicating.不要通过共享内存进行通信,而是通过通信共享内存。 明确并发和并行的两个概念:并发不是并行:并发是由切换时间来实现“同时”运行,并行是多核多线程goroutine 通过通信来共享内存,而不是共享内存来通信。这样就可以较为充分利用多核CPU和内存资源的同时,又相对比较可靠,”协程”也是类似种”管道”的思维模式,在这里,通信显得比较重要,这些Golang已经做了底层化实现,对开发者来说比较简便一些,大部分精力放在管理好这些阀门出入口即可。Linux的管道是非常优秀的设计。 这个应该不是说以前的方案或其他语言处理思路是错误、不佳或有偏差的,历史上很多方案往往受制于硬件的运算性能综合因素考虑,是当时权衡下来的最好的方案,比如硬件成本太高等,现在随着软硬件的快速发展和成本低廉有这个条件来做这个事情了。终归是有当时基于现实情况的各种因素考量。无论性能再怎么快,必须把可靠性放在重要位置,一个相对不可靠的方案,程序运行速度再快将毫无意义,我想这是Golang从软件工程化考虑的重要考量吧。 Golang设计哲学和Unix应该是一致的:大道至简,“简”是对大规模工程化系统开发中最好的思考范畴,虽万变仍不离其宗。 并发&并行的编程理念对开发人员来说是未来编程思维的常态,事物发展的规律。 至少在公司产品和项目开发中,Golang至少是未来主力的语言,因为随着数据的不断增长,必须要一种从性能上,可靠性上和开发上相对最合适的技术选型,Golang是很符合这一点的,Golang不只是一个简单的编程语言这么简单。C系的开发语言经久不衰很重要的原因就是追求用最简单的方式解决现实问题,Golang是未来考虑的主力开发语言。 个人实践思路示意: ——— Jack Liu 秋 Date:2017-05-30","link":"/6480b1cd.html"},{"title":"Go:init()","text":"init()init()函数特性 init()在main包执行之前 init()自动执行,不能显示调用 同一个Go文件中可定义多个init()函数,顺序执行 同一个package中不同文件,将文件名按字符串进行字母和数字自然排序,之后顺序调用各文件中的init() import导入: 字符 _ (下划线)操作,本质是引入package且不直接使用内部函数,仅仅调用init()初始化 按照import导入顺序调用包中init() package的init()在被引用时自动被调用 package存在依赖,调用顺序为最后被依赖的最先被执行初始化 package被其他多个包import,只能被初始化一次","link":"/5ae2eb16.html"},{"title":"Go:interface","text":"interface 接口go:interface{}、断言与类型转换 Go的接口更大的作用是声明方法集合,而非类型约束。 interface{}可用于向函数传递任意类型的变量,但对于函数内部,该变量仍然为interface{}类型(空接口类型),故必须进行类型断言确认类型后检查才能使用(不能直接隐式转换)。 接口类型向普通类型的转换称为类型断言(运行期确定)。 接口转换基本原则 普通类型 =》 接口类型:编译器运行时隐式转换。 接口类型 =》普通类型:必须显式类型断言。 超集和子集转换关系:超转子可以,子转超不可以。 断言推荐方式:1234567b,ok:=a.([]int)if ok{ ...}//断言失败在编译阶段不会报错,故很可能出现断言失败导致运行错误。 1.断言的作用:使用interface{}时,解决空接口类型向普通类型转换的类型转换问题; 2.普通类型之间的转换,使用显式的类型转换,否则后果严重不可控。 interface值传递注意事项: 如果接口实现方法,类型自己的实现使用的是值接收器,那么在传递值的时候无论使用指针还是值都可以。 如果接口实现方法,类型自己的实现使用的是指针接收器,那么在传递值的时候必须传递地址。12345原因:编译器不能自动获得一个未声明地址。结构体类型定义的方法可以被该结构体的指针类型调用;而结构体类型调用该指针类型的方法时是被转换成指针,不是直接调用。接口实现方法时,用指针类型实现的接口函数只能算是指针类型实现的,用结构体类型实现的方法也作为是指针类型实现。 interface{} 与 []interface{}12var dataSlice []int = foo()var interfaceSlice []interface{} = dataSlice 编译错误 1cannot use dataSlice (type []int) as type []interface { } in assignment 任何类型赋值给interface{},不能把任何类型的切片赋值到[]interface{} 不能 直接将某些[]MyType切片赋值给[]interface{}, 他们背后代表的数据意义不同。 12345678910 //编译错误//t := []int{1, 2, 3, 4} wrong //var s []interface{} = t //正确t := []int{1, 2, 3, 4} //right s := make([]interface{}, len(t)) for i, v := range t { s[i] = v } 接口转换 利用类型推断,可判断接口对象是否某个具体的接口或类型。 还可用 switch 做批量类型判断,不支持 fallthrough。 超集接口对象可转换为子集接口,反之出错。 原因: []interface{}类型 不是 interface{}类型, 它是一个切片,切片元素的类型恰好是interface{}。 []interface{}类型变量拥有特定的内存结构,这在编译时就已经决定。每个interface{}占两个字(word),一个字用于存放interface存放的类型,另一个字用于存放实际数据或者是指向数据的指针。于是长度为N的[]interface{}类型切片背后是一个N2字长的一块数据。这与一般的[]MyType类型切片不同,相同长度的[]MyType切片背后的数据块大小为Nsizeof(MyType)字长。 使用方式:如果想得到一个元素为任意类型的列表的容器,并且在索引其中元素之前会把它转换为原本的数据类型,可以直接使用interface{}即可。此种方式很通用(如果 不是编译时类型安全 的)也很快速。 接口类型内存布局(原理)interface在内存上实际由两个成员组成 tab指向虚表(Virtual Table) data则指向实际引用的数据。 虚表描绘了实际的类型信息及该接口所需要的方法集。 接口的底层结构runtime.h 123456789101112131415161718192021struct Iface{ Itab* tab; void* data;};struct Itab{ InterfaceType* inter; Type* type; void (*fun[])(void);};struct Itab{ InterfaceType* inter; Type* type; void (*fun[])(void);};//只有 tab 和 data 都为 nil 时,接口才等于 nil。 接口Demo: 123456789101112131415161718192021222324252627package mainimport ( "fmt")type People interface { Do()}type Student struct { UserId int UserName string}func (s Student) Do() { s.UserName = "Jack Liu" return}func main() { stu := Student{1, "Jack"} p := People(stu)// //a.Do() fmt.Printf("%T %v", p, p)} People接口本身,底层含有tab虚表和data实际存储的值两部分; :123456789101112131415161718192021222324**通过接口进行函数调用** ,实际的操作其实就是```p.tab->fun[0](p.data)```; ###### 参考Go和C++的虚表的异同:* C++: * c++ 的虚表是在编译时生成的,注意:表现出的多态是在runtime运行时决定; * 每个class创建了一个方法集(虚表); * 当子类重写父类的虚函数时,就将表中的相应函数指针改为子类自己实现的函数; * 如果没有则指向父类的实现; * 当面临多继承时,C++对象结构里就会存在多个虚表指针,每个虚表指针指向该方法集的不同部分。* Go: * Go 接口的虚表是在runtime运行时生成; * ``` p := People(Student{1, "Jack"})```生成People接口对应于Student类型的虚表,并将其缓存。###### 原因:* Go无继承关系,采用的是组合方式,所以不能进行虚表初始化(多少类型实现了某个接口,单个类型到底实现了多少接口这让编译器无从获知.* 选择在运行时生成虚表是自然的方案,放到runtime运行时,只要在需要接口的去分析一下类型是否实现了接口的所有方法即可,这样避免了去维护大量继承和绑定关系的心智负担,此并不会带来性能上的太大问题。* Go接口组合的方案和C++反其道而行之,本质上来说,各有优缺点。#### 接口技巧让编译器检查,以确保某个类型实现接口。``` var _ fmt.Stringer = (*Data)(nil) ```某些时候,让函数直接 "实现" 接口能省不少事。 type Tester interface { Do()} type FuncDo func()func (self FuncDo) Do() { self() } func main() { var t Tester = FuncDo(func() { println(“Hello, World!”) }) t.Do()}","link":"/512e106c.html"},{"title":"Go:JSON","text":"JSONjson.Marshal()默认转换规则:1.布尔型转换为 JSON 后仍是布尔型 , 如true -> true2.浮点型和整数型转换后为JSON里面的常规数字,如 1.23 -> 1.233.字符串将以UTF-8编码转化输出为Unicode字符集的字符串,特殊字符比如<将会被转义为\\u003c 4.数组和切片被转换为JSON 里面的数组,[]byte类会被转换为base64编码后的字符串,slice的零值被转换为null5.结构体会转化为JSON对象,并且只有结构体里边以大写字母开头的可被导出的字段才会被转化输出,而这些可导出的字段会作为JSON对象的字符串索引6.转化一个map 类型的数据结构时,该数据的类型必须是 map[string]T(T 可以是encoding/json 包支持的任意数据类型) json.Unmarshal()注意:如果JSON中的字段在Go目标类型中不存在,json.Unmarshal() 函数在解码过程中会丢弃该字段。未知类型,遵循规则:1.JSON中的布尔值将会转换为Go中的bool类型2.数值会被转换为Go中的float64类型3.字符串转换后还是string类型4.JSON数组会转换为[]interface{} 类型5.JSON对象会转换为map[string]interface{}类型6.null值会转换为nil","link":"/72259ecc.html"},{"title":"Go:new,make,struct{}","text":"new,make,struct{} 函数 适用范围 返回值 填充值 make() 仅限创建类型(slice map channel) 引用,make返回复杂的结构为slice时:它是一个包含3个域的结构体:指向slice中第一个元素的指针,slice的长度,以及slice的容量。 非零值,make(T, args)返回一个初始化的(而不是置零),类型为T的值(而不是*T)。之所以有所不同,是因为这三个类型的背后引用了使用前必须初始化的数据结构 new() 所有类型 指针,new返回一个指向已清零内存的指针,而make返回一个复杂的结构。 零值,new(T)会为T类型的新项目,但new它并不初始化内存,只是将其置零 备注:直接使用struct{} 来初始化strut时,返回的是一个struct类型的值,而不是指针。","link":"/96edd24c.html"},{"title":"Go:Map","text":"Map 要点注意事项 map 是引用类型的: 内存用 make 方法来分配。 new,永远用 make 来构造 map。new() 分配了一个引用对象,你会获得一个空引用的指针,相当于声明了一个未初始化的变量并且取了它的地址。 当 map 增长到容量上限的时候,如果再增加新的 key-value 对,map 的大小会自动加 1。所以出于性能的考虑,对于大的 map 或者会快速扩张的 map,即使只是大概知道容量,也最好先标明。 特殊用法用切片作为 map 的值 12mp1 := make(map[int][]int)mp2 := make(map[int]*[]int) 只遍历键KEY时,使用下面的形式,无须将值改为匿名变量形式,忽略值即可: 123for key := range mapData { //Code ...} map清空:无相关函数和方法。截至Go 1.12,清空唯一办法就是重新 make 一个新的 map。但担心垃圾回收的效率,Go的GC的回收效率远高于一个清空函数。 map并发安全注意事项sync.Map有以下特性: 无须初始化,直接声明即可。 sync.Map 不能使用 map 的方式进行取值和设置等操作,而是使用 sync.Map 的方法进行调用。 Store 表示存储, Load 表示获取, Delete 表示删除。 遍历操作 Range加回调函数,回调函数返回内部遍历出来的值。 Range 参数中的回调函数的返回值功能是: 需要继续迭代遍历时,返回 true; 终止迭代遍历时,返回false。 12345678910#定义var mapData sync.Map#遍历所有sync.Map中的键值对mapData.Range(func(k, v interface{}) bool { fmt.Println("list-kv: %v , %v", k, v) return true})","link":"/73ca5667.html"},{"title":"Go:null judge","text":"null judgeint空值是0,string空值是””而不是null或者nil(区别Slice空值是长度为0的map空值是nil,error空值是nil,struct空值是一个“所有成员都是空值”的空Struct而不是nil, 不能单纯地判断一个struct是不是nil,因为它永远不可能是nil,可以通过返回一个error来判断是否为空,golang标准库里的常见做法:if err != nil","link":"/31b42193.html"},{"title":"Go:pointer","text":"pointer 指针基于指针对象的方法当调用一个函数时,会对其每一个参数值进行拷贝,如果一个函数需要更新一个变量,或者函数的其中一个参数实在太大我们希望能够避免进行这种默认的拷贝,这种情况下我们就需要用到指针了。对应到我们这里用来更新接收器的对象的方法,当这个接受者变量本身比较大时,我们就可以用其指针而不是对象来声明方法,如下: func (p *Point) ScaleBy(factor float64) { p.X *= factor p.Y *= factor}这个方法的名字是(Point).ScaleBy。这里的括号是必须的;没有括号的话这个表达式可能会被理解为(Point.ScaleBy)。 在现实的程序里,一般会约定如果Point这个类有一个指针作为接收器的方法,那么所有Point的方法都必须有一个指针接收器,即使是那些并不需要这个指针接收器的函数。我们在这里打破了这个约定只是为了展示一下两种方法的异同而已。 只有类型(Point)和指向他们的指针(*Point),才是可能会出现在接收器声明里的两种接收器。此外,为了避免歧义,在声明方法时,如果一个类型名本身是一个指针的话,是不允许其出现在接收器中的,比如下面这个例子: type P intfunc (P) f() { / … */ } // compile error: invalid receiver type想要调用指针类型方法(*Point).ScaleBy,只要提供一个Point类型的指针即可,像下面这样。 r := &Point{1, 2}r.ScaleBy(2)fmt.Println(*r) // “{2, 4}”或者这样: p := Point{1, 2}pptr := &ppptr.ScaleBy(2)fmt.Println(p) // “{2, 4}”或者这样: p := Point{1, 2}(&p).ScaleBy(2)fmt.Println(p) // “{2, 4}”不过后面两种方法有些笨拙。幸运的是,go语言本身在这种地方会帮到我们。如果接收器p是一个Point类型的变量,并且其方法需要一个Point指针作为接收器,我们可以用下面这种简短的写法: p.ScaleBy(2)编译器会隐式地帮我们用&p去调用ScaleBy这个方法。这种简写方法只适用于“变量”,包括struct里的字段比如p.X,以及array和slice内的元素比如perim[0]。我们不能通过一个无法取到地址的接收器来调用指针方法,比如临时变量的内存地址就无法获取得到: Point{1, 2}.ScaleBy(2) // compile error: can’t take address of Point literal但是我们可以用一个Point这样的接收器来调用Point的方法,因为我们可以通过地址来找到这个变量,只要用解引用符号来取到该变量即可。编译器在这里也会给我们隐式地插入*这个操作符,所以下面这两种写法等价的: pptr.Distance(q)(*pptr).Distance(q)这里的几个例子可能让你有些困惑,所以我们总结一下:在每一个合法的方法调用表达式中,也就是下面三种情况里的任意一种情况都是可以的: 不论是接收器的实际参数和其接收器的形式参数相同,比如两者都是类型T或者都是类型*T: Point{1, 2}.Distance(q) // Pointpptr.ScaleBy(2) // Point或者接收器实参是类型T,但接收器形参是类型T,这种情况下编译器会隐式地为我们取变量的地址: p.ScaleBy(2) // implicit (&p)或者接收器实参是类型*T,形参是类型T。编译器会隐式地为我们解引用,取到指针指向的实际变量: pptr.Distance(q) // implicit (pptr)如果命名类型T(译注:用type xxx定义的类型)的所有方法都是用T类型自己来做接收器(而不是T),那么拷贝这种类型的实例就是安全的;调用他的任何一个方法也就会产生一个值的拷贝。比如time.Duration的这个类型,在调用其方法时就会被全部拷贝一份,包括在作为参数传入函数的时候。但是如果一个方法使用指针作为接收器,你需要避免对其进行拷贝,因为这样可能会破坏掉该类型内部的不变性。比如你对bytes.Buffer对象进行了拷贝,那么可能会引起原始对象和拷贝对象只是别名而已,但实际上其指向的对象是一致的。紧接着对拷贝后的变量进行修改可能会有让你意外的结果。 译注: 作者这里说的比较绕,其实有两点: 不管你的method的receiver是指针类型还是非指针类型,都是可以通过指针/非指针类型进行调用的,编译器会帮你做类型转换。在声明一个method的receiver该是指针还是非指针类型时,你需要考虑两方面的内部,第一方面是这个对象本身是不是特别大,如果声明为非指针变量时,调用会产生一次拷贝;第二方面是如果你用指针类型作为receiver,那么你一定要注意,这种指针类型指向的始终是一块内存地址,就算你对其进行了拷贝。熟悉C或者C艹的人这里应该很快能明白。","link":"/a753c2b9.html"},{"title":"Go:polymorphism","text":"polymorphism多态特性 多态:同一件事情由于条件不同产生的结果不同; 由于Go语言中结构体不能相互转换,所以没有结构体类型的多态,只有基于接口的多态。这符合Go语言对面向对象的诠释; 多态和泛型的区别 泛型是当我们使用这个泛型类时候再去确定这个类里面的成员具体什么类型的,两者本质不是一个层次,多态不能实现泛型。 多态是在继承层面上,即根据实际运行时候来确定具体的实现。 泛型本质上并不是多态的一种特例,多态并不能实现泛型。 引入泛型的本质是为了安全,把编译时能发现的错误不带到runtime运行时。","link":"/165668dc.html"},{"title":"Go:fmt.Printf() 格式化占位符","text":"fmt.Printf() 格式化占位符格式符 fmt.Printf("%v", variable) 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485# 【通用占位符】 v 值的默认格式。 %+v 添加字段名(如结构体) %#v 相应值的Go语法表示 %T 相应值的类型的Go语法表示 %% 字面上的百分号,并非值的占位符 # 【布尔值】 %t true 或 false# 【整数值】 %b 二进制表示 %c 相应Unicode码点所表示的字符 %d 十进制表示 %o 八进制表示 %q 单引号围绕的字符字面值,由Go语法安全地转义 %x 十六进制表示,字母形式为小写 a-f %X 十六进制表示,字母形式为大写 A-F %U Unicode格式:U+1234,等同于 "U+%04X"# 【浮点数及复数】 %b 无小数部分的,指数为二的幂的科学计数法, 与 strconv.FormatFloat中的 'b' 转换格式一致。例如 -123456p-78 %e 科学计数法,例如 -1234.456e+78 %E 科学计数法,例如 -1234.456E+78 %f 有小数点而无指数,例如 123.456 %g 根据情况选择 %e 或 %f 以产生更紧凑的(无末尾的0)输出 %G 根据情况选择 %E 或 %f 以产生更紧凑的(无末尾的0)输出# 【字符串和bytes的slice表示】 %s 字符串或切片的无解译字节 %q 双引号围绕的字符串,由Go语法安全地转义 %x 十六进制,小写字母,每字节两个字符 %X 十六进制,大写字母,每字节两个字符# 【指针】 %p 十六进制表示,前缀 0x 这里没有 'u' 标记。若整数为无符号类型,他们就会被打印成无符号的。# 【精度和对齐方式】 〔输出最少宽度〕〔.精度〕〔长度〕类型 "%-md" :左对齐,若m比实际少时,按实际输出。 "%m.ns":输出m位,取字符串(左起)n位,左补空格,当n>m or m省略时m=n "%m.nf":输出浮点数的输出宽度对齐,m为宽度,n为小数点右边数位# 【宽度和精度】 指示符(`f')为例: %f: 默认宽度和精度 %mf 宽度m, 默认精度 %.nf 默认宽度, 精度n %m.nf 宽度m, 精度n %m.f 宽度m, 精度0 若遇到浮点数的指示符(`f')的话,它表示小数部分的位数。 若遇到浮点数的指示符(`e', `E', `g', `G')的话,它表示有效位数 若将精度设为`*'的话,将从参数中提取精度的值 整数的指示符(`d', `i', `b', `o', `x', `X', `u') 其中对于字符串%s或者浮点类型%f,来说,精度可以截断数据的长度 "%-md" :左对齐,若m比实际少时,按实际输出。 "%m.ns":输出m位,取字符串(左起)n位,左补空格,当n>m or m省略时m=n# 【显示参数占位符】 %[2]d, %[1]d 以%d为例:先输出第二个值,再输出第一个值.# 【特殊格式标识符】 + 总打印数值的正负号;对于%q(%+q)保证只输出ASCII编码的字符。 - 左对齐 # 备用格式: 为八进制添加前导 0(%#o), 为十六进制添加前导 0x(%#x)或0X(%#X),为 %p(%#p)去掉前导 0x; 对于 %q,若 strconv.CanBackquote 返回 true, 就会打印原始(即反引号围绕的)字符串; 如果是可打印字符,%U(%#U)会写出该字符的 Unicode编码形式(如字符 x 会被打印成 U+0078 'x')。 ' ' (空格)为数值中省略的正负号留出空白(% d); 以十六进制(% x, % X)打印字符串或切片时,在字节之间用空格隔开 0 填充前导的0而非空格;对于数字,这会将填充移到正负号之后","link":"/8aaf9686.html"},{"title":"Go:reflect 反射","text":"reflect 反射反射性能的一般原则基准测试结果的数值分析的一般原则建议: 能使用原生代码时,尽量避免反射操作。 提前缓冲反射值对象,对性能有很大的帮助。 避免反射函数调用,实在需要调用时,先提前缓冲函数参数列表,并且尽量少地使用返回值。 reflect 包类型定义12345678910111213141516171819202122232425262728293031323334//reflect 包类型定义type Kind Signconst ( Invalid Kind = iota // 非法类型 Bool // 布尔型 Int // 有符号整型 Int8 // 有符号8位整型 Int16 // 有符号16位整型 Int32 // 有符号32位整型 Int64 // 有符号64位整型 Uint // 无符号整型 Uint8 // 无符号8位整型 Uint16 // 无符号16位整型 Uint32 // 无符号32位整型 Uint64 // 无符号64位整型 Uintptr // 指针 Float32 // 单精度浮点数 Float64 // 双精度浮点数 Complex64 // 64位复数类型 Complex128 // 128位复数类型 Array // 数组 Chan // 通道 Func // 函数 Interface // 接口 Map // 映射 Ptr // 指针 Slice // 切片 String // 字符串 Struct // 结构体 UnsafePointer // 底层指针)","link":"/53f6e137.html"},{"title":"Go:slice 切片本质","text":"go 切片:本质数组Go的切片是在数组之上的抽象数据类型,因此在了解切片之前必须要要理解数组。数组类型由指定和长度和元素类型定义。数组不需要显式的初始化;数组元素会自动初始化为零值: Go的数组是值语义。一个数组变量表示整个数组,它不是指向第一个元素的指针(比如C语言的数组)。当一个数组变量被赋值或者被传递的时候,实际上会复制整个数组。(为了避免复制数组,你可以传递一个指向数组的指针,但是数组指针并不是数组。)可以将数组看作一个特殊的struct,结构的字段名对应数组的索引,同时成员的数目固定。 切片数组虽然有适用它们的地方,但是数组不够灵活,因此在Go代码中数组使用的并不多。但是,切片则使用得相当广泛。切片基于数组构建,但是提供更强的功能和便利。切片的类型是 []T,T 是切片元素的类型。和数组不同的是,切片没有固定的长度。切片的字面值和数组字面值很像,不过切片没有指定元素个数:切片可以内置函数 make 创建,函数签名为:func make([]T, len, cap) []TT 代表被创建的切片元素的类型。函数 make 接受一个类型、一个长度和一个可选的容量参数。调用 make 时,内部会分配一个数组,然后返回数组对应的切片。当容量参数被忽略时,它默认为指定的长度。下面是简洁的写法:s := make([]byte, 5)可以使用内置函数 len 和 cap 获取切片的长度和容量信息。len(s) == 5cap(s) == 5 长度和容量之间的关系。零值的切片类型变量为 nil。对于零值切片变量,len 和 cap 都将返回 0。切片也可以基于现有的切片或数组生成。切分的范围由两个由冒号分割的索引对应的半开区间指定。切片的开始和结束的索引都是可选的;它们分别默认为零和数组的长度。 切片的本质一个切片是一个数组切割区间的描述。它包含了指向数组的指针,切割区间的长度,和容量(切割区间的最大长度)。切片并不复制整个切片元素。它创建一个新的切片执行同样的底层数组。这使得切片操作和数组索引一样高效。因此,通过一个新切片修改元素同样会影响到原始的切片。切片增长不能超出其容量。增长超出切片容量将会导致运行时异常,就像切片或数组的索引超出范围引起异常一样。同样,不能使用小于零的索引去访问切片之前的元素。切片生长(复制和追加)要增加切片的容量必须创建一个新的、更大容量的切片,然后将原有切片的内容复制到新的切片。整个技术是一些支持动态数组语言的常见实现。循环中复制的操作可以由 copy 内置函数替代。copy 函数将源切片的元素复制到目的切片。它返回复制元素的数目。func copy(dst, src []T) intcopy 函数支持不同长度的切片之间的复制(它只复制最小切片长度的元素)。此外,copy 函数可以正确处理源和目的切片有重叠的情况。但大多数程序不需要完全的控制,因此Go提供了一个内置函数 append,用于大多数场合;它的函数签名:func append(s []T, x …T) []Tappend函数将x追加到切片s的末尾,并且在必要的时候增加容量。如果是要将一个切片追加到另一个切片尾部,需要使用…语法将第2个参数展开为参数列表。可以声明一个零值切片(nil),然后在循环中向切片追加数据: 可能的“陷阱”切片操作并不会复制底层的数组。此层的数组将被保存在内存中,直到它不再被引用。有时候可能会因为一个小的内存引用导致保存所有的数据。","link":"/647ce9cb.html"},{"title":"Go:string","text":"string常用拼接方法 += 来拼接 bytes.Buffer strings.Builder ( >= go1.10 ) 拼接方法性能对比 使用 += 的方法性能是最慢的,性能消耗相对最大; Buffer和Builder性能相差无几,Builder在内存的使用上要略优于Buffer; 官方推荐strings.Builder,优点: 性能好,代码清晰;","link":"/765e2161.html"},{"title":"Go:关于Go语言:结构体(Struct)-方法(Method)-接收者(Receiver)类型的适用场景选择和命名约定(Go官方建议)","text":"关于Go语言:结构体(Struct)-方法(Method)-接收者(Receiver)类型的适用场景选择和命名约定(Go官方建议)何时使用值类型场景1.如果接受者是一个 map,func 或者 chan,使用值类型(因为它们本身就是引用类型)。2.如果接受者是一个 slice,并且方法不执行 reslice 操作,也不重新分配内存给 slice,使用值类型。3.如果接受者是一个小的数组或者原生的值类型结构体类型(比如 time.Time 类型),而且没有可修改的字段和指针,又或者接受者是一个简单地基本类型像是 int 和 string,使用值类型就好了。 一个值类型的接受者可以减少一定数量的垃圾生成,如果一个值被传入一个值类型接受者的方法,一个栈上的拷贝会替代在堆上分配内存(但不是保证一定成功),所以在没搞明白代码想干什么之前,别因为这个原因而选择值类型接受者。 使用指针类型场景1.如果方法需要修改接受者,接受者必须是指针类型。2.如果接受者是一个包含了 sync.Mutex 或者类似同步字段的结构体,接受者必须是指针,这样可以避免拷贝。3.如果接受者是一个大的结构体或者数组,那么指针类型接受者更有效率。4.从此方法中并发的调用函数和方法时,接受者可以被修改吗?一个值类型的接受者当方法调用时会创建一份拷贝,所以外部的修改不能作用到这个接受者上。如果修改必须被原始的接受者可见,那么接受者必须是指针类型。5.如果接受者是一个结构体,数组或者 slice,它们中任意一个元素是指针类型而且可能被修改,建议使用指针类型接受者,这样会增加程序的可读性。 Receiver接收者的命名1.社区约定的接受者命名是类型的一个或两个字母的缩写(像 c 或者 cl 对于 Client)。2.避免使用泛指的名字像是 me,this 或者 self,也避免使用过度描述的名字;3.如果你在一个地方使用了 c,那么就不要在别的地方使用 cl; 自我总结一般使用场景下,决定是否使用指针,看数据单体(结构体、接口等等…)容量的大小(特别注意:注意切片slice、字典map、管道channel本身引用类型,底层本身是指针调用),语言层面数据单体存储的形式是否本身就是指针类型,数据单体的作用范围和操作的范围,归根结底,还是要结合实际具体业务场景提前规划好数据结构,开发中多考虑数据单体的拷贝成本是否过高。Go官方的使用建议,也是在Go内存分配和数据存储原理上的归纳总结。Go语言虽然有指针但是没有包含指针计算,指针的操作也非常简单(这点考量特别地好,简单的结构可以让GC最低成本地监测内存运行状态,避免过多的指针关联,利于GC内存管理和回收)。","link":"/b5903345.html"},{"title":"Go:switch","text":"switchswitch 注意事项 fallthrough不能用在switch的最后一个分支。","link":"/8709d8d0.html"},{"title":"Go:struct","text":"struct面向对象Class类的底层实现从某些方面说就是结构体,对象的引用就是指针,只是语言把他们封装起来了而已。Golang的Struct结构体(源于C语言,但又有别于C)的灵活性:go语言中并没有像C++,Java语言中这类的Class,它只含有像C语言中的结构体,用结构体和指针等特性,完成一个类的作用,很巧妙的使用了指针和结构体,不仅是go的面向对象,包括go语言中的map等操作都是借助了结构体。其实,说白了,C++、Java等面向对象的语言中,类的底层实现就是结构体,对象的引用就是指针,只是语言把他们封装起来了而已。很多人刚接触面向对象很不理解这些东西也应该缘于此。 或者说,面向对象的封装在某种意义上是以牺牲灵活特性的为代价的一种抽象简化。 所有高级语言(PHP、Java、Python、JavaScript等等…)的数组Array、字典map、Slice切片、Json等结构类型往往只是叫法不一样,多少都源于C系或者受到C系的Struct结构体思想的影响,在某些特定领域内,做了一些针对性的解决方案。 PHP就是c语言实现的一套高级“程序”语言,只不过是这套“程序化的语言”的规范和语法等机制可以用来快速做web领域的事情,通过解释器,转成底层语言完成代码的最终执行。 这也印证了很多答案往往追根溯源都在计算机数据结构基础里没有捷径可以走。 golang struct注意事项:对于struct类型来说,字段的先后顺序是非常关键的。如果两个struct类型包含了完全相同的字段,但是排列顺序不同或者进行了部分合并,那么这两个struct就是不同的类型! 如果struct字段是大写字母开头,那么该字段就是导出的(包外可见),这也符合Go语言的可见性规则。因此一个struct可以同时包含导出和未导出的变量。","link":"/527244e6.html"},{"title":"Go:package time","text":"package timetime 转换注意事项Go语言指定时间原点 123456789101112package mainimport ( "time" "fmt")func main() { //当前时间格式化,记忆规律:创始年份2016 | 一 | 二 | 三(15时,即 3 pm) | 四 | 五 nowTime := time.Now().Format("2006-01-02 15:04:05") fmt.Println(nowTime)}","link":"/b5c88baa.html"},{"title":"Go:type关键词总结","text":"type关键词总结type 用法: 定义结构体 定义接口 类型别名 类型定义 类型开关 类型定义和类型别名的区别:区别就是类型定义是完全定义了一种新的类型,而类型别名只是给现有的类型取了一个别名alias。(编译器会替换成基本类型。) Type常见Demo定义结构体12type Demo struct {} 定义接口12type Demoer interface {} 类型别名12type Demo string 类型定义12type handle func(str string) 类型开关1234567891011func Demo(params ...interface{}) { for i, x := range params { switch x.(type) { case bool: fmt.Printf("type #%d is bool",i) default: fmt.Printf("type is unknow") } }} 类型注意事项类型比较备注:参考Go文档type说明: 命名类型(简单类型),有类型名称如 int, int64, float, string, bool. 还有自定义的命名类型。 非命名类型(复杂类型),没类型名称 array slice, map,func(){}, interface{}。但是chan类型是可以==比较。 slice 内存不连续,底层对象分开放的,不能直接比较; map 内存不连续,底层对象独立存放,不能直接比较; chan 内存是连续的,单一对象,可以直接比较; 当比较两个命名类型的时候,类型名称必须一样;当比较命名类型和非命名类型的时候,底层类型一样即可。 比较基于两个原则:1.内存底层基本类型;2.类型本身是否确定类型或不稳定类型; 空接口值比较 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950package mainimport ( "fmt" "reflect")type T1 []stringtype T2 []stringfunc main() { foo0 := []string{} foo1 := T1{} foo2 := T2{} fmt.Println(reflect.TypeOf(foo0)) fmt.Println(reflect.TypeOf(foo1)) fmt.Println(reflect.TypeOf(foo2)) // Output: // []string // main.T1 // main.T2 //编译通,反之亦然 //foo1 = foo0 //foo0 = foo1 // 编译不通过 // 错误提示:cannot use foo2 (type T2) as type T1 in assignment foo2 = foo0 foo1 = foo2 //cannot //编译通过:chan ch1 := make(chan int) ch2 := make(chan int) fmt.Println(ch1 == ch2) //编译不通过:slice s1 := []int{1,2} s2 := []int{2,1} fmt.Println(s1 == s2) //编译不通过:map m1 := make(map[int]int) m2 := make(map[int]int) fmt.Println(m1 == m2)} 类型可比较性判断原则:底层数据结构类型是否稳定和一致 类型 说明 map 宕机错误,不可比较 切片([]T) 宕机错误,不可比较 通道(channel) 可比较,必须由同一个 make 生成,也就是同一个通道才会是 true,否则为 false 数组([容量]T) 可比较,编译期知道两个数组是否一致 结构体 可比较,可以逐个比较结构体的值 函数 可比较","link":"/49c8ae5b.html"},{"title":"LinuxCentos7-Systemd-Service自定义编写Service应用服务配置说明整理","text":"Centos7-Systemd-Service自定义编写Service应用服务配置说明整理系统基本service服务配置目录(此目录勿动,一般情况下只放系统核心基础服务配置,否存放应用注册类服务配置):/etc/systemd/system 自定义服务配置管理目录(存放自定义应用注册类服务和第三方服务类配置):/usr/lib/systemd/system/ 自定义.service配置文件 (权限:754) 格式(以应用app-run.service为例, 执行文件作好超时处理!):12345678910111213141516171819202122232425[Unit]Description="app-run@Author Jack Liu Process Daemon" # 服务描述After=rc-local.service # 服务类别: # 例启动顺序(默认在rc-local.service之后调用执行) [Service]Type=forking # 优先使用forking方式: # (遵循传统Unix做法,设置PIDFile=选项 # 帮助systemd准确定位该服务的主进程)PIDFile=/var/run/app-run.pid # 设置应用进程的PID(缺省)Environment="GOPATH=/usr/local/go" # 环境变量设置,可设置多个Environment=项 # 备注:Environment= 或 EnvironmentFile= # 引用文件, 两种方式皆可ExecStart=/data/auto_run.sh start # 调用启动可执行文件: # (Service配置全部使用绝对路径, # 可执行文件内命令用绝对的路径格式) ExecReload=/data/auto_run.sh reload # 重新加载(缺省)ExecStop=/data/auto_run.sh stop # 停止服务(缺省)DefaultTimeoutStartSec=30 # 服务启动允许的最大时长,超时时间(默认无单位:秒) # 单位:"ms"(毫秒), "s"(秒), "min"(分钟), # "h"(小时), "d"(天), "w"(周) PrivateTmp=True # 是否分配独立的临时空间(缺省) [Install]WantedBy=multi-user.target EnvironmentFile默认约定引用存放目录一般为:/usr/lib/systemd/system/app-run.service.d/environment.conf(格式:Key=Value) Service服务管理常用操作命令12345678在开机时启用一个服务:systemctl enable app-run.service 在开机时禁用一个服务:systemctl disable app-run.service启动一个服务:systemctl start app-run.service 关闭一个服务:systemctl stop app-run.service 重启一个服务:systemctl restart app-run.service 显示一个服务的状态:systemctl status app-run.service 查看服务是否开机启动:systemctl is-enabled app-run.service 查看已启动的服务列表:systemctl list-unit-files|grep enabled 注意:服务无法执行检查SElinux是否开启,自行关闭SElinux。","link":"/27eb580e.html"},{"title":"OpenSSH 配置文件体系","text":"全局配置文件12345678910111213141516171819202122232425262728293031323334/etc/ssh/# 保存Diffie-Hellman组通过密钥交换构建安全的网络传输层/etc/ssh/moduli# 缺省的SSH客户端配置文件/etc/ssh/ssh_config# sshd守护进程的配置文件/etc/ssh/sshd _config# sshd守护进程的DSA私钥/etc/ssh/ssh_host_dsa_key# sshd守护进程的DSA公钥/etc/ssh/ssh_host_dsa_key.pub# sshd守护进程的SSH协议版本1的RAS私钥/etc/ssh/ssh_host_key# sshd守护进程的SSH协议版本1的RAS公钥/etc/ssh/ssh_host_key.pub# sshd守护进程的SSH协议版本2的RAS私钥/etc/ssh/ssh_host_rsa_key# sshd守护进程的SSH协议版本2的RAS公钥/etc/ssh/ssh_ho st_rsa_key.pub# sshd守护进程的PAM配置文件/etc/pam.d/sshd # sshd服务的配置文件/etc/sysconfig/sshd 用户1234567891011121314151617181920212223242526~/.ssh/# 服务器用来验证SSH客户端的客户公钥~/.ssh/authorized_keys# 用户的DSA私钥~/.ssh/id_dsa # 用户的DSA公钥~/.ssh/id_dsa. pub# 用户的SSH协议版本2的RSA私钥~/.ssh/id_rsa # 用户的SSH协议版本2的RSA公钥~/.ssh/id_rsa.pub# 用户的SSH协议版本1的RSA私钥 ~/.ssh/identity# 用户的SSH协议版本的RSA公钥~/.ssh/identity.pub# 用户连接的SSH服务器公钥~/.ssh/known_hosts SSH Tunnel 安全隧道","link":"/fc526729.html"},{"title":"Centos7-chattr权限问题导致锁定文件无法解锁且root用户无法编辑","text":"chattrchattr 命令,专门用来修改文件或目录的隐藏属性。在部分linux发行版中,部分存在chattr本身执行权限移除的默认设置,导致root用户无法编辑相关文件且chattr命令无法修改文件属性。解决的思路是先解决chattr本身的文件属性,确保chattr可用。 解决方案如下: 解决方案1234567891011cp /usr/bin/chattr /usr/bin/chattr_bakchmod 755 /usr/bin/chattr_bakchattr_bak -i /usr/bin/chattrchmod 755 /usr/bin/chattrls -la /usr/bin/chattr","link":"/e7a4c7e2.html"},{"title":"firewalld services 防火墙内嵌服务","text":"firewalld services 防火墙内嵌服务Configuration file path: /usr/lib/firewalld/services按字母顺序: 12345678910amanda-client.xml amanda-k5-client.xml bacula-client.xml bacula.xml bitcoin-rpc.xml bitcoin-testnet-rpc.xml bitcoin-testnet.xml bitcoin.xml ceph-mon.xml ceph.xml 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697cfengine.xml condor-collector.xml ctdb.xml dhcpv6-client.xml dhcpv6.xml dhcp.xml dns.xml docker-registry.xml dropbox-lansync.xml elasticsearch.xml freeipa-ldaps.xml freeipa-ldap.xml freeipa-replication.xml freeipa-trust.xml ftp.xml ganglia-client.xml ganglia-master.xml high-availability.xml https.xmlhttp.xmlimaps.xml imap.xml ipp-client.xml ipp.xml ipsec.xml iscsi-target.xml kadmin.xml kerberos.xml kibana.xml klogin.xml kpasswd.xml kshell.xml ldaps.xml ldap.xml libvirt-tls.xml libvirt.xml managesieve.xml mdns.xml mosh.xml mountd.xml mssql.xml ms-wbt.xml mysql.xml nfs.xml nrpe.xml ntp.xml openvpn.xml ovirt-imageio.xml ovirt-storageconsole.xml ovirt-vmconsole.xml pmcd.xml pmproxy.xml pmwebapis.xml pmwebapi.xml pop3s.xml pop3.xml postgresql.xml privoxy.xml proxy-dhcp.xml ptp.xml pulseaudio.xml puppetmaster.xml quassel.xml radius.xml RH-Satellite-6.xml rpc-bind.xml rsh.xml rsyncd.xml samba-client.xml samba.xml sane.xml sips.xml sip.xml smtp-submission.xml smtps.xml smtp.xml snmptrap.xml snmp.xml spideroak-lansync.xml squid.xml ssh.xmlsynergy.xml syslog-tls.xml syslog.xml telnet.xml tftp-client.xml tftp.xml tinc.xml tor-socks.xml transmission-client.xml vdsm.xml vnc-server.xml wbem-https.xml xmpp-bosh.xml xmpp-client.xml xmpp-local.xml xmpp-server.xml ssh.xml:1234567<?xml version="1.0" encoding="utf-8"?><service> <short>SSH</short> <description>Secure Shell (SSH) is a protocol for logging into and executing commands on remote machines. It provides secure encrypted communications. If you plan on accessing your machine remotely via SSH over a firewalled interface, enable this option. You need the openssh-server package installed for this option to be useful.</description> <port protocol="tcp" port="22"/></service>","link":"/147227b8.html"},{"title":"Linux login shell信息展示类(neofetch、motd等banner类提示信息展示)导致的rsync服务不可用问题注意事项","text":"终端报错信息(以Debian 11 系统为例):protocol version mismatch — is your shell clean?系统环境 OS: Debian GNU/Linux 11 (bullseye) x86_64 Host: KVM RHEL 7.6.0 PC (i440FX + PIIX, 1996) Kernel: 5.10.0-22-amd64 问题描述 【问题】:导致rsync服务同步失败,报错信息: "protocol version mismatch — is your shell clean?"。 【原因】:rsync等工具非常依赖于shell执行时没有任何输出。 【建议】:不建议在.bashrc中输出neofetch、banner类和motd类提示信息,在~/.profile中source ~/.bashrc可以避免此问题,但需注意.profile循环引用执行问题。 login shell载入文件信息相关文件:12/etc/profile~/.profile .profile 引用 .bashrc: 12345if [ "$BASH" ]; then if [ -f ~/.bashrc ]; then . ~/.bashrc fifi 输出展示信息放在~/.bashrc文件内引发的问题(rsync为例): 12345678910# ~/.bashrc: executed by bash(1) for non-login shells.# Note: PS1 and umask are already set in /etc/profile. You should not# need this unless you want different defaults for root.# PS1='${debian_chroot:+($debian_chroot)}\\h:\\w\\$ '# umask 022# problem(rsync):protocol version mismatch — is your shell clean?neofetch 【问题】:导致rsync服务同步失败,报错信息: "protocol version mismatch — is your shell clean?"。【原因】:rsync等工具非常依赖于shell执行时没有任何输出。 【建议】:不建议在.bashrc中输出neofetch、banner类和motd类提示信息,在~/.profile中source ~/.bashrc可以避免此问题,但需注意.profile循环引用执行问题。 例如:~/.profile 1234567if [ "$BASH" ]; then if [ -f ~/.bashrc ]; then . ~/.bashrc fifineofetch 总结:在Linux发行版系统中,一些高度依赖.bashrc的系统工具或者命令(例如rsync),会引发不可执行或者执行有误等问题,要留意Linux文件加载的顺序以及执行规则。","link":"/954c81e2.html"},{"title":"Rocky Linux系统初始化常用基础命令和工具包的便捷安装脚本(ljq@GitHub)","text":"Description: A script to check system version and installed tools on Rocky Linux.(脚本描述:一个用于检查系统版本和Rocky Linux系统初始化工具的便捷脚本,安装系统常用命令和工具包。)Author: Jackliu (ljq@GitHub)Usage: ./rocky-linux-init.shVersion: 1.0Date: 2023-07-04License: MITPage Site: https://github.com/ljqrelease-version/rocky-linux/rocky-linux-init.sh Rocky Linux 发行版本默认检查安装基础工具包含: 123456789101112131415# Define tools list in lowercasetools=( "vim" # 0 "ping" # 1 "net-tools" # 2 "firewalld" # 3 "tar" # 4 "gzip" # 5 "bzip2" # 6 "wget" # 7 "curl" # 8 "python 3" # 9 "git" # 10 "ncurses" # 11) 备注:脚本简单灵活,可根据需要自行配置相关常用命令,方便系统管理员快速初始化系统基础环境。","link":"/96f1067a.html"},{"title":"HomeBrew Mirror to accelerate Settings (HomeBrew 镜像加速解决源下载缓慢卡顿问题和超大软件包等待问题)","text":"HomeBrew 环境配置以及卡顿问题处理关键环境变量配置推荐使用清华源镜像替换:https://mirrors.ustc.edu.cn/ 1234567# 文件列表(对应以下镜像仓库地址)homebrew Folder-------------------------------homebrew-bottleshomebrew-cask-versions.githomebrew-cask.githomebrew-core.git 环境变量替换配置项:.bash_profile 或 .zshrc 12345678export HOMEBREW_BREW_GIT_REMOTE="https://mirrors.ustc.edu.cn/brew.git"export HOMEBREW_CORE_GIT_REMOTE="https://mirrors.ustc.edu.cn/homebrew-core.git"export HOMEBREW_BOTTLE_DOMAIN="https://mirrors.ustc.edu.cn/homebrew-bottles/bottles"# close brew auto update (是否关闭自动更新,开发环境推荐设置为true,手动更新)export HOMEBREW_NO_AUTO_UPDATE=true 软件镜像地址替换: 1234567891011替换核心软件仓库cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core"git remote set-url origin https://mirrors.ustc.edu.cn/homebrew-core.git替换 cask 软件仓库cd "$(brew --repo)"/Library/Taps/caskroom/homebrew-caskgit remote set-url origin https://mirrors.ustc.edu.cn/homebrew-cask.git替换 cask-versions 软件仓库cd "$(brew --repo)"/Library/Taps/homebrew/homebrew-cask-versionsgit remote set-url origin https://mirrors.ustc.edu.cn/homebrew-cask-versions.git 针对部分官方软件包的下载处理(需要开发经验)关键目录12345# HomeBrew 安装源缓存目录:~/Library/Caches/Homebrew# 软件配置目录:/usr/local/etc 针对较大低速软件包的处理 软件安装原理:homebrew-tap源配置的.rb软件源有两个关键字段配置: 12url ""sha256 "" brew install [软件名]命令通过sha256校验值在Cache生成对应的类似临时文件(不同软件包有所不同)[sha256]--[软件]-[版本].[文件格式].incomplete,部分软件会在./downloads目录下载完成后文件变成类似[sha256]--[软件名]-[版本].[文件格式],在上层目录生成软链,执行软件包解压或者转移到应用目录下。 如果既想使用homebrew管理软件包同时又忍受不了软件长时间的低速下载,可使 以上可以通过下方式完成软件包的替换(建议有开发经验人员是用,否则缓存目录可能产生冗余文件):1.下载指定版本软件包(注意软件版本和对应的sha256值);2.执行brew install [软件],记录下临时文件的sha256值和文件名以及版本好;3.将已下载的软件包命名成[sha256]–[软件]-[版本].[文件格式]方式;4.再次执行brew install [软件],此时成功的话会提示软件已下载完成,直接执行安装操作(如果仍提示下载软件,检查sha256文件名是否符合对应版本的软件包值要求)。","link":"/2dc6af80.html"},{"title":"LUA Syntax","text":"LUA Notes注释 单行注释-- 多行注释 123--[[ 注释--]] 或 123--[[ 注释 ]] 多行注释遇到用[[和]]表示的字符串就会提前结束,可以用—-[=[ 注释内容 ]=]来解决 123--[=[ 注释 ]=] 程序块chunklua语法-程序块(chunk) lua解释器以程序块的方式处理lua代码 每一段可执行的lua代码都可以成为程序块 lua程序块指一条或多条合法的可执行语句 一个程序块由一条或多条lua语句构成 简单的程序块:一条语句 复杂的程序块:多条不同语句及函数定义构成语句结尾的分号缺省,如一行多哥语句,建议分号隔开 数据类型table (创建不同的数据类型:数组、字典等) table 数据结构本身支持多态,定义灵活,是数组和集合的混合物 table 使用关联数组,可以使用人艺类型值作索引,但值不能为nil table 是不固定大小的,你可以哥怒自己需要进行扩展 lua的模块(mobule)、包(package)、和对象(Object)本身也是基于table的 12345678t = { "a", "b", "c", [4] = "d", [5] = "f", [6] = function(){}} Table 操作 操作 方法 用途 连接 table.concat (table [, sep [, start [, end]]]) concat是concatenate(连锁, 连接)的缩写. table.concat()函数列出参数中指定table的数组部分从start位置到end位置的所有元素, 元素间以指定的分隔符(sep)隔开。 新增 table.insert (table, [pos,] value) 在table的数组部分指定位置(pos)插入值为value的一个元素. pos参数可选, 默认为数组部分末尾. maxn table.maxn (table) 指定table中所有正数key值中最大的key值. 如果不存在key值为正数的元素, 则返回0。(Lua5.2之后该方法已经不存在了) 移除 table.remove (table [, pos]) 返回table数组部分位于pos位置的元素. 其后的元素会被前移. pos参数可选, 默认为table长度, 即从最后一个元素删起。 排序 table.sort (table [, comp]) 对给定的table进行升序排序。 变量 默认变量为全局变量,包含方法内变量,如果设置局部变量,则添加修饰符local(此处极易导致异常和Bug,谨慎使用,尽可能使用局部变量),使用局部变量的好处: 避免命名冲突和和变量误覆盖 访问局部变量的速度更快 避免逻辑错误缺陷 全局变量删除:只需要将变量赋值为nil。 运算符运算符号 关系运算符: < 、>、<= 、>= 、 == 、 ~=(不等于) 逻辑运算符: and or not 连接运算符: .. (两个点) 运算注意事项 “0” 和 0 (false,不相等) nil只等于nil本身 逻辑运算符false和nil是假(false),其他为true(包括0也是true) and和or的运算结果不是true和false,而和两个操作数相关: a and b – 如果a为false,则返回a,否则返回b a or b – 如果a为true,则返回a,否则返回b lua比较数字按传统的数字大小进行,比较字符串按字母的顺序进行(但字母顺序依赖于本地环境(字符编码或其他顺序等不同)) 函数 () 括号仅用于函数中使用,其他地方可缺省忽略 循环while1234while(condition)do statementsend for123for var=exp1,exp2,exp3 do --end repeat123repeat statementsuntil( condition ) break 和 gotogoto语法格式:goto Label; Label 的格式为:: Label :: 12345678local a = 1::label:: print("--- goto label ---")a = a+1if a < 3 then goto label -- a 小于 3 的时候跳转到标签 labelend continue官方未内置,可通过其他方式实现不提供continue的原因:Lua-FAQ:This is a common complaint. The Lua authors felt that continue was only one of a number of possible new control flow mechanisms (the fact that it cannot work with the scope rules of repeat/until was a secondary factor.)Lua作者认为continue非必要特性且只是许多新控制流机制中的一种,未加入此特性,continue关键字在repeat/until结构中会引发出现一些问题。 lua中模拟“continue”的几种方法: 使用repeat循环包住需要要continue跳过的代码,使用break跳出循环, 需要注意的是,lua中的repeat语句,在循环条件为真的时候退出 123456789for i = 1, 10 do repeat if i%2 == 0 then break end print(i) break until trueend 使用while循环包住需要continue跳过的代码, 使用break跳出循环 123456789for i = 1, 10 do while true do if i%2 == 0 then break end print(i) break endend 在lua5.2版本之后,可以使用goto语句来模拟 1234567for i = 1, 10 do if i%2 == 0 then goto continue end print(i) ::continue::end 模块与包 local 对象,外部模块无法访问 环境变量自定义设置 文件路径以 “;” 号分隔,最后的 2 个 “;;” 表示新加的路径后面加上原来的默认路径。 注意事项:Mac OS 系统下,export LUA_PATH="~/lua/?.lua;;"在.zshrc中如果在用户home路径下自定义模块路径,会被当成~字符,不会解析用户的home路径no file '~/lua/modules/module.lua',故建议应该写为绝对路径。 1234#LUA_PATH#export LUA_PATH="~/lua/?.lua;;"export LUA_PATH="/Users/iotd/lua/?.lua;;" 12345678910111213141516171819202122-- 文件名为 module.lua-- 定义一个名为 module 的模块module = {} -- 定义一个常量module.constant = "这是一个常量" -- 定义一个函数function module.func1() io.write("这是一个公有函数!\\n")end -- 外部无法访问到local function func2() print("这是一个私有函数!")end function module.func3() func2()end return module 元表","link":"/a1a26b3d.html"},{"title":"MacOS English terminal Chinese garbled characters solution (MacOS英文环境终端中文内容乱码问题解决)","text":"Problem presentation123456LANGUAGE = "en_US:en",LC_ALL = (unset),LC_CTYPE = "UTF-8",LANG = "en_US.UTF-8"warning: Falling back to a fallback locale ("en_US.UTF-8"). 此问题常见于MacOS系统升级、OpenSSL升级后,terminal终端ssh远程链接时发出警告。 Solution在MacOS本地终端: 1sudo vi /etc/ssh/ssh_config 注释默认配置: 1SendEnv LANG LC_* 重启终端即可。 References参考","link":"/bb19ba9f.html"},{"title":"Hexo cdn.jsdelivr.net A low cost solution for CDN invalidation(Hexo cdn.jsdelivr.net 等部分CDN引用无效的一种低成本解决方案)","text":"原因:cdn.jsdelivr.net在2021年12月20号国内已经无法使用,导致部分引用此引用此cdn资源的hexo生成站点js依赖和错误页面功能异常。 临时低成本解决方案: 考虑到不同的hexo站点使用的插件各有不同,且引用的第三方js库存在差异,故考虑采用低成本的方式解决。大概思路是在生成的部分文件里,替换相应的站点域名,实现在deploy之前完成文件路径的转换。 举例来说,也是本人遇到的问题,常用的js库jsdelivr CDNhttps://[CDN地址]/npm/js-base64/base64.min.js: 准备工作(主题icarus为例): 1.下载对应的无效js文件到本地; 2.文件放置在(对应创建CDN路径文件夹)themes/icarus/source/npm/js-base64/base64.min.js; 站点根路径生成常用命令封装了一个简单的操作命令脚本(hexo-deploy.sh): 12345678910111213141516171819#!/usr/bin/env sh# author: Jack Liu# Description: (debug | deploy git) scriptif [ "$1" == "debug" ]; then echo "---------------- Debug Mode ----------------" hexo clean && hexo s exitfihexo clean && hexo gecho "---------------- Invalid CDN switch local path file ----------------"# MacOS下sed和Linux发行版之间的区别,MacOS包含备份保护机制,注意sed -i ''find ./public -name "*.html" -type f -exec sed -i '' 's/\\/\\/cdn\\.jsdelivr\\.net\\//\\//g' '{}' \\;hexo decho 'hexo deploy run is ok !' 警告: 脚本包含替换操作!执行脚本前请严格检查命令可行性,防止误操作。 MacOS下sed和Linux发行版之间的区别,MacOS包含备份保护机制,注意sed -i ‘’ 执行成功后./public下路径替换会为/npm/js-base64/base64.min.js 备注:其他无效CDN域名引用,参考类似方法,注意sed命令转义。","link":"/bafde551.html"},{"title":"macOS系统升级导致brew发行包Nginx服务Service无法启动或启动失败问题解决(MacOS Ventura 13.3)","text":"macOS系统升级导致brew发行包Nginx服务Service无法启动或启动失败问题解决(MacOS Ventura 13.3)系统版本:MacOS Ventura 13.3Nginx服务启动失败问题描述:MacOS系统升级导致brew发行包Nginx服务Service无法启动或启动失败,提示隐私或权限问题,系统限制root用户运行。 解决方案:此脚本用于解决MacOS升级新版后,基于Homebrew发行的Nginx包守护服务无法启动运行问题。此问题一般由MacOS更新的权限隐私策略与nginx守护服务权限冲突导致服务无法启动。该脚本通过直接操作nginx服务进程实现服务的快捷管理,增加常用进程基础检查操作,封装快捷操作脚本。 ljq@GitHub Homebrew安装nginx: 1brew install nginx macos_nginx_brew_service.sh 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115#!/usr/bin/env bash# Author: Jack Liu# Date Time: 2023-04-07 20:06# Site: https://github.com/ljq# Blog: https://www.defense.ink# Email: ljqlab@163.com# Description: 🍎 The nginx distribution provided by hombrew daemon service shortcut script.# help infoUSEAGE="[usage]: [-s | s | status] [start | restart | reload | stop] [-h | -help | --help] [-v | -V | --version]"HELP_INFO=$(cat <<EOF[help information]Description: 🍎 This script is used to resolve the problem that the Homebrew-based Nginx package daemon service cannot be started after the new version of MacOS is updated. This problem is usually caused by the conflict between the permission privacy policy updated by MacOS and the permission of the nginx daemon service. This script manages the service by directly manipulating the nginx service process.Command usage: -v|-V|version: Show current nginx version information. -h|-help|--help: Show help info. -s|s|status: Nginx process status. start|restart|reload|stop: Service operation.EOF)# set variablessh_file=$0argv1=$1nginx_conf_file=$(brew --prefix)/etc/nginx/nginx.confnginx_bin=$(brew --prefix nginx)/bin/nginx# main# descriptionif [ "$argv1" = "" ]; then echo -e "[brew's nginx service shortcut script]\\n"fi# initialization checkif [ ! -x "$(command -v brew)" ]; then echo -e "[WARNING] Homebrew is not installed." exitfiif [ ! -f "$nginx_bin" ]; then echo -e "[WARNING] The version of nignx provided by homebrew is not installed." exitfiif [ ! -f "$nginx_conf_file" ]; then echo -e "[WARNING] The nignx.conf file provided by homebrew is not exist." exitfi# nginx config checkchk_status=$(${nginx_bin} -t 2>&1)if [[ $chk_status =~ "syntax is ok" ]] && [[ $chk_status =~ "test is successful" ]]; then #echo -e "[INFO] The nginx.conf syntax is ok.\\n" echo ""else echo -e "[ERROR] The nginx.conf syntax is incorrect." exitfi# execcase "$argv1" in "-v"|"-version"|"--version"|"-V") ${nginx_bin} -V ;; "-s"|"s"|"status") serv_process=$(ps -ef | grep nginx | grep -v "grep\\|${sh_file}") if [ "$serv_process" = "" ]; then echo -e "[NOTICE] Nginx service status is stoped.\\n" else echo -e "[NOTICE] Nginx service status is running.\\n" fi ;; "start") serv_process=$(ps -ef | grep nginx | grep -v "grep\\|${sh_file}") if [ "$serv_process" = "" ]; then echo -e "[NOTICE] Nginx service is starting ...\\n" ${nginx_bin} -c $nginx_conf_file else echo -e "[WARNING] Nginx service is already running. Do not repeat operation.\\n" fi ;; "restart") echo -e "[NOTICE] Nginx service is restarting ...\\n" ${nginx_bin} -s stop ${nginx_bin} -c $nginx_conf_file ;; "reload") echo -e "[NOTICE] Nginx service is reloading ...\\n" ${nginx_bin} -s reload ;; "stop") ${nginx_bin} -s stop echo -e "[NOTICE] Nginx service has stoped.\\n" ;; "-t") ${nginx_bin} -t ;; "-h"|"-help"|"--help") echo -e "${HELP_INFO}\\n" ;; *) echo -e "[WARNING] Parameter is invalid or missing. Please run help command: ${sh_file} -h\\n" ;;esacexit 脚本使用案例脚本增加可执行权限:1chmod +x macos_nginx_brew_service.sh 查看帮助:1./macos_nginx_brew_service.sh -h 常用操作1234567891011121314# 启动./macos_nginx_brew_service.sh start# 重启./macos_nginx_brew_service.sh restart# 状态./macos_nginx_brew_service.sh status# 重载./macos_nginx_brew_service.sh reload# 停止./macos_nginx_brew_service.sh stop# nginx 版本./macos_nginx_brew_service.sh -V 参数说明:1234567-v|-V|version: Show current nginx version information.-h|-help|--help: Show help info.-s|s|status: Nginx process status.start|restart|reload|stop: Service operation. macos_nginx_brew_service.sh ljq@GitHub","link":"/8c6562df.html"},{"title":"《如何创建一家像谷歌一样的公司》(How to start Google)- paulgraham - 转载","text":"文章原文地址:https://paulgraham.com/google.html (作者:保罗格雷厄姆)《如何创建一家像谷歌一样的公司》(How to start Google)2024 年 3 月 (这是我给14岁和15岁的孩子们做的演讲,内容是如果他们以后想要创业的话现在该怎么做。很多学校认为他们应该告诉学生一些关于创业的事情。这就是我认为他们应该告诉他们的。 )你们中的大多数人可能认为,当您被释放到所谓的现实世界中时,您最终将不得不找到某种工作。 这不是真的,今天我要谈谈一个可以用来避免找工作的技巧。 诀窍是创办自己的公司。 所以这并不是逃避工作的伎俩,因为如果你创办自己的公司,你会比从事普通工作时更加努力。 但你会避免工作带来的许多烦人的事情,包括老板告诉你该做什么。 从事自己的项目比从事别人的项目更令人兴奋。 而且你还可以变得更加富有。 事实上,这是真正致富的标准方式。 如果你看一下偶尔在媒体上公布的最富有的人名单,你会发现几乎所有人都是通过创办自己的公司来实现这一目标的。 创办自己的公司可以意味着任何事情,从创办理发店到创办谷歌。 我来这里是要谈谈这个连续体的一个极端。 我将告诉您如何启动 Google。 位于谷歌连续体末端的公司在年轻时被称为初创公司。 我之所以了解他们,是因为我和妻子杰西卡创办了一家名为 Y Combinator 的公司,它基本上是一家初创工厂。 自 2005 年以来,Y Combinator 已资助了 4000 多家初创公司。 因此,我们确切地知道您创办一家初创公司需要什么,因为我们在过去 19 年里一直在帮助人们做到这一点。 当我说我要告诉你如何启动 Google 时,你可能认为我在开玩笑。 您可能会想“我们怎样才能启动 Google?” 但这实际上就是那些创建谷歌的人在创建之前所想的。 如果你告诉谷歌创始人拉里·佩奇和谢尔盖·布林,他们即将创办的公司有一天将价值超过一万亿美元,他们的脑袋一定会爆炸。 当你开始创业时,你所能知道的就是它似乎值得追求。 你不知道它会变成一家价值数十亿的公司还是一家倒闭的公司。 因此,当我说我要告诉你如何创办谷歌时,我的意思是我要告诉你如何才能创办一家像谷歌一样有机会成为谷歌的公司。 谷歌。 [1] 你如何从现在的状态发展到可以成功创业的地步? 你需要三件事。 你需要擅长某种技术,你需要对你要构建的东西有一个想法,你需要联合创始人来创办公司。 如何才能擅长技术? 您如何选择擅长哪种技术? 这两个问题都有相同的答案:致力于自己的项目。 不要试图猜测基因编辑、法学硕士或火箭是否会成为最有价值的技术。 没有人能预测这一点。 只做你最感兴趣的事情。 你会在你感兴趣的事情上比你正在做的事情更加努力,因为你认为你应该这样做。 如果您不确定要擅长什么技术,那就擅长编程。 这一直是过去 30 年初创企业中位数的来源,而且在未来 10 年可能不会改变。 那些在学校上计算机科学课程的人此时可能会想,好吧,我们已经解决了这个问题。 我们已经被教授了所有关于编程的知识。 但抱歉,这还不够。 你必须致力于自己的项目,而不仅仅是在课堂上学习东西。 您可以在计算机科学课程上取得好成绩,而无需真正学习编程。 事实上,你可以从顶尖大学获得计算机科学学位,但仍然不擅长编程。 这就是为什么科技公司在雇用你之前都会让你参加编码测试,无论你在哪里上的大学或者你在那里表现得如何。 他们知道成绩和考试结果不能证明什么。 如果你真的想学习编程,你就必须从事自己的项目。 这样你学得更快。 想象一下,您正在编写一款游戏,并且您想要在其中执行某些操作,但您不知道如何执行。 你会发现比在课堂上学习任何东西要快得多。 不过,您不必学习编程。 如果您想知道什么才算技术,它几乎包括您可以使用“制造”或“构建”一词描述的所有内容。 所以焊接、制作衣服、制作视频都算数。 无论你对什么最感兴趣。关键的区别在于你是在生产还是只是在消费。 您是在编写电脑游戏,还是只是玩游戏? 这就是截止点。 苹果公司的创始人史蒂夫·乔布斯(Steve Jobs)在青少年时期就花时间学习书法——那种美丽的书法。 文章原文地址:https://paulgraham.com/google.html (作者:保罗格雷厄姆)","link":"/de20129e.html"},{"title":"php laravel artisan 基础命令","text":"php artisan 常用命令php artisan 常用命令,注意一些版本差异。 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465命令 说明 备注php artisan make:resource [parameter] 创建api返回格式化资源 >=5.4版本可用php artisan make:rule [parameter] 创建validate规则 >=5.4版本可用php artisan make:exception [parameter] 创建异常类 >=5.4版本可用php artisan make:factory [parameter] 创建工厂类 >=5.4版本可用php artisan package:discover 重置包的缓存信息 >=5.4版本可用php artisan storage:link [parameter] Create a symbolic link from "public/storage" to "storage/app/public" >=5.4版本可用php artisan view:clear 清楚所有已编译的视图文件 >=5.4版本可用 命令 说明 备注php artisan clear-compiled 清除编译后的类文件 php artisan down 使应用程序进入维修模式 php artisan up 退出应用程序的维护模式 php artisan env 显示当前框架环境 php artisan fresh 清除包含框架外的支架 php artisan help 显示命令行的帮助 php artisan list 列出命令 php artisan migrate 运行数据库迁移 php artisan env 显示当前框架环境 php artisan optimize 为了更好的框架去优化性能 php artisan serve 在php开发服务器中服务这个应用 --port 8080,--host 0.0.0.0php artisan tinker 在应用中交互 php artisan app:name [parameter] 设置应用程序命名空间php artisan auth:clear-resets 清除过期的密码重置密钥 未使用过php artisan cache:clear 清除应用程序缓存 php artisan cache:table 创建一个缓存数据库表的迁移 php artisan config:cache 创建一个加载配置的缓存文件 php artisan config:clear 删除配置的缓存文件 php artisan db:seed 数据库生成模拟数据 php artisan event:generate 生成event和listen 需要实现配置eventserviceprivoderphp artisan make:command [parameter] 创建一个新的命令处理程序类 php artisan make:console [parameter] 生成一个Artisan命令 php artisan key:generate 设置程序密钥 php artisan make:controller [parameter] 生成一个资源控制类 php artisan make:middleware [parameter] 生成一个中间件 php artisan make:migration [parameter] 生成一个迁移文件 php artisan make:model [parameter] 生成一个Eloquent 模型类 php artisan make:provider [parameter] 生成一个服务提供商的类 php artisan make:request [parameter] 生成一个表单消息类 php artisan migrate:install [parameter] 创建一个迁移库文件 php artisan make:migration [parameter] 生成一个迁移文件 php artisan migrate:refresh [parameter] 复位并重新运行所有的迁移 php artisan migrate:reset [parameter] 回滚全部数据库迁移 php artisan migrate:rollback [parameter] 回滚最后一个数据库迁移 php artisan migrate:status 显示列表的迁移 php artisan queue:failed 列出全部失败的队列工作 php artisan queue:failed-table [parameter] 创建一个迁移的失败的队列数据库工作表 php artisan queue:flush 清除全部失败的队列工作 php artisan queue:forget [parameter] 删除一个失败的队列工作 php artisan queue:listen [parameter] 监听一个确定的队列工作php artisan queue:restart 重启现在正在运行的所有队列工作 php artisan queue:retry 重试一个失败的队列工作 php artisan queue:subscribe 订阅URL,放到队列上 php artisan queue:table 创建一个迁移的队列数据库工作表 php artisan queue:work 进行下一个队列任务php artisan route:cache 为了更快的路由登记,创建一个路由缓存文件 php artisan route:clear 清除路由缓存文件 php artisan route:list 列出全部的注册路由 php artisan schedule:run 运行预定命令 php artisan session:table 创建一个迁移的SESSION数据库工作表 php artisan vendor:publish 发表一些可以发布的有用的资源来自提供商的插件包 baum包命令命令 说明 备注php artisan baum Get Baum version notice. php artisan baum:install [parameter] Scaffolds a new migration and model suitable for Baum","link":"/4b985e6d.html"},{"title":"Tribute to the great legendary philanthropist and programmer Bram Moolenaar, the original author and software maintainer of VIM(致敬伟大传奇的慈善家和程序员Bram Moolenaar,VIM最初作者和软件维护者)","text":"Tribute to the great legendary philanthropist and programmer Bram Moolenaar, the original author and software maintainer of VIM(致敬伟大传奇的慈善家和程序员Bram Moolenaar,VIM最初作者和软件维护者)Bram Moolenaar is a Dutch computer programmer and the creator of the famous text editor Vim. Bram Moolenaar was born in 1961 in The Hague, Netherlands. In his career, he has worked in multiple fields such as software development and system management. However, his most well-known contribution was the creation of Vim, a popular text editor. In 1991, the standard editor Vi for Unix at that time had very limited versions on the MS-DOS platform, and Bram Moolenaar decided to develop a more powerful and scalable editor. He released the first version of Vim (Vi IMimproved) in 1991 and continued to drive its subsequent development and improvement. Vim is a free and open source text editor with powerful features and high customizability. It supports multiple operating systems, including Unix/Linux, Microsoft Windows, Mac OS, and has become one of the preferred tools for programmers and developers. In addition to Vim, Bram Moolenaar has also actively participated in the development and maintenance of multiple open source projects, making significant contributions to the software industry. As an excellent programmer and creator, Bram Moolenaar is widely praised and respected for his dedication to Vim and contributions to the open source community. His work and achievements have had a great impact on the global programmer community and continue to inspire a new generation of software developers. 致敬伟大传奇的慈善家和程序员Bram Moolenaar,VIM最初作者和软件维护者Bram Moolenaar是一位荷兰的计算机程序员,他是著名的文本编辑器Vim的创作者。 Bram Moolenaar于1961年出生在荷兰的海牙。在他的职业生涯中,他曾经从事过软件开发和系统管理等多个领域的工作。然而,他最为人所知的贡献是他创造了Vim这一广受欢迎的文本编辑器。 在1991年,当时的Unix的标准编辑器Vi在MS-DOS平台上的版本非常有限,Bram Moolenaar决定开发一个更加强大和可扩展的编辑器。他于1991年发布了第一个版本的Vim(Vi IMproved),并继续推动其后续的发展和改进。 Vim是一个自由、开源的文本编辑器,具有强大的功能和高度的可定制性。它支持多种操作系统,包括Unix/Linux、Microsoft Windows、Mac OS等,并且成为程序员和开发者们的首选工具之一。 除了Vim,Bram Moolenaar还积极参与了多个开源项目的开发与维护,为软件界做出了重要的贡献。 作为一名优秀的程序员和创造者,Bram Moolenaar因其对Vim的奉献和对开源社区的贡献而受到广泛的赞誉和尊重。他的工作和成就为全球的程序员社区带来了极大的影响,并且持续地激励着新一代的软件开发者们。 R.I.P 🕯️🙏","link":"/aa470947.html"},{"title":"The Legend of 1900","text":"1、All that city you just couldn’t see an end to it.城市那么大,看不到尽头。 2、The end? Please? Can you please just show me where it ends?尽头在哪里?可以给我看看尽头么? 3、It was all very final on that gangway and I was grant too in my over coat. I cut quite a figure, and I was getting off, guaranteed. That wasn’t the problem.当年,我踏上跳板,不觉得困难。我穿上大衣,很神气,自觉一表人才,有决心,有把握,有信心。 4、It wasn’t what I saw that stopped me, Max, it was what I didn’t see. Do you understand that? What I didn’t see.我停下来,不是因为所见,是因为所不见。你明不明白?是因为看不见的东西。 5、In all that sprawling city, there was everything except an end. There was no end.连绵不绝的城市,什么都有,除了尽头,没有尽头。 6、What I did not see was where the whole thing came to an end, the end of the world.我看不见城市的尽头,我需要看见世界尽头。 7、Take a piano, hmm? The keys begin, the keys end. You know there are 88 of them. Nobody can tell you different. They are not infinite拿钢琴来说,键盘有始也有终。有88个键,错不了,并不是无限的。 8、You are infinite. And on those keys, the music that you can make is infinite.音乐是无限的。在琴键上,奏出无限的音乐 9、I like that. That I can live by.我喜欢那样,我应付得来。 10、You get me up on that gangway and you rill out in front of me a keyboard of millions of keys, Millions and billions of keys that never end.走过跳板,前面的键盘有无数的琴键。 11、That’s the truth, Max, they never end. That keyboard is infinite.事实如此,无穷无尽,键盘无限大。 12、And if that keyboard is infinite, then on that keyboard there is no music you can play.无限大的键盘,怎奏得出音乐? 13、You are sitting on the wrong bench. That’s God’s piano.不是给凡人奏得,是给上帝奏得。 14、Christ! Did you see the streets? Just the street—–there were thousands of them.唉!只是街道,已经好几千条。 15、How do you do it down there? How do you choose just one?上了岸,何去何从? 16、One woman, one house, one piece of land to call your own, one landscape to look at, one way to die. All that world just weighing down on you. You don’t even know where it comes to an end.爱一个女人,住一间屋子,买一块地,望一个景,走一条死路。太多选择,我无所适从,漫无止境,茫茫无际。 17、Aren’t you ever just scared of breaking apart at the thought of it? The enormity of it.思前想后,你不怕精神崩溃?那样的日子怎么过? 18、I was born on this ship, and the world passed me by.我生于船,长与船,世界千变万化 19、But 2000 people at a time, and there were wishes here.这艘船每次只载客两千,既载人,有载梦想。 20、But never more than fit between prow and stern.但范围离不开船头与船尾之间。 21、You played put your happiness, but on a piano that was not infinite! I learned to live that way.在有限的钢琴上,我自得其乐,我过惯那样的日子。 22、Land?Land is a ship too big for me. It’s a woman too beautiful, it’s avoyage too long, a perfume too strong, it’s music I don’t know how tomake.陆地?对我来说,陆地是艘太大的船,是位太美的美女。是条太长的航程,是瓶太香的香水,是篇无从弹奏得乐章。 23、I can never get off this ship. I’m blessed I can step off my life.我没法舍弃这艘船,我宁可舍弃自己的生命。 24、After all, I don’t exist for anyone.反正,世间每人记得我。 25、You are the exception, Max. You are the only one who knows I’m here. You are a minority, and you’d better get used of it.除了你,Max,只有你知道我在这里,你属于少数,你最好习惯一下。 26、Forgive me, my friend, but I’m not getting off.朋友,原谅我。我不下船了。 27、Hey,Max! Imagine the music I could play with two right arms. Hope I can find a piano up there.两条右臂能谈出什么音乐? 希望天堂有钢琴。 28、“陆上的人喜欢寻根问底,虚度了大好光阴。冬天忧虑夏天的姗姗来迟,夏天则担心冬天的将至。所以他们不停四处游走,追求一个遥不可及、四季如夏的地方—我并不羡慕。” Why why why why why… I think land people waste a lot of time wondering why. Winter comes they can’t wait for summer; summer comes they’re living dread of winter. That’s why you’re never tired of travelling, with chasing some place far away, where there’s always summer. That doesn’t sound like a good bet to me. 29、“所有那些城市,你就是无法看见尽头。尽头?拜托!拜托你给我看它的尽头在哪?当时,站在舷梯向外看还好。我那时穿着大衣,感觉也很棒,觉得自己前途无量,然后我就要下船去。放心!完全没问题!可是,阻止了我的脚步的,并不是我所看见的东西,而是我所无法看见的那些东西。你明白么?我看不见的那些。在那个无限蔓延的城市里,什么东西都有,可惟独没有尽头。根本就没有尽头。我看不见的是这一切的尽头,世界的尽头。”“All that city. You just couldn’t see the end to it. The end? Please? You please just show me where it ends? It was all very fine on that gangway. And I was grand too, in my overcoat. I cut quite a figure. And I was getting off. Guaranteed. There was no problem. It wasn’t what I saw that stopped me, Max. It was what I didn’t see. You understand that? What I didn’t see. In all that sprawling city there was everything except an end. There was no end. What I did not see was where the whole thing came to an end. The end of the world… ” 30、“键盘有始有终,你确切知道 88 个键就在那儿,错不了。它并不是无限的,而音乐,才是无限的。你能在键盘上表现的音乐是无限的,我喜欢这样,我能轻松应对。 ! ”“Take a piano. The keys begin, the keys end. You know there are eightyeight of them, nobody can tell you any different. They are not infinite. You are infinite. And on these keys the music that you can make is infinite. I like that. That I can live by. ” 31、“你把我推到舷梯上然后扔给我一架有百万琴键的钢琴,百万千万的没有尽头的琴键,那是事实,max,它们没有尽头。那键盘是无限延伸的。然而如果琴键是无限的,那么在那架琴上就没有你能弹奏的音乐,你坐错了地方,那是上帝的钢琴。”“You get me up on that gangway and you’re rolling out in front of me a keyboard of millions of keys, millions and billions of keys that never end, and that’s the truth, Max. That they never end. That keyboard is infinite. And if that keyboard is infinite, then on that keyboard there is nomusic you can play. You’re sitting on the wrong bench. That’s God’s piano. ” 32、“天啊!你……你看过那些街道吗?仅仅是街道,就有上千条!你下去该怎么办?你怎么选择其中一条来走?怎么选择“属于你自己的”一个女人,一栋房子,一块地,或者选择一道风景欣赏,选择一种方法死去。 ”“Christ! Did, did you see the streets? Just the streets… There were thousands of them! And how do you do it down there?How do you choose just one? One woman, one house, one piece of land to call your own, one landscape to look at, one way to die… ” 33、“那个世界好重,压在我身上。你甚至不知道它在哪里结束,你难道从来不为自己生活在无穷选择里而害怕得快崩溃掉吗?”“All that world is weighing down on me, you don’t even know where it comes to an end, and aren’t you ever just scared of breaking apart at the thought of it? The enormity of living it? ” 34、“我是在这艘船上出生的,整个世界跟我并肩而行,但是,行走一次只携带两千人。这里也有欲望,但不会虚妄到超出船头和船尾。你用钢琴表达你的快乐,但音符不是无限的。我已经习惯这么生活。”“I was born on this ship, and the world passed me by, but two thousand people at a time. And there were wishes here,but never more than fit between prow and stern. You played out your happiness, but on a piano that was not infinite. I learned to live that way. ” 35、“陆地?陆地对我来说是一艘太大的船,一个太漂亮的女人,一段太长的旅行,一瓶太刺鼻的香水,一种我不会创作的音乐。我永远无法放弃这艘船,不过幸好,我可以放弃我的生命。反正没人记得我存在过,而你是例外,max,你是唯一一个知道我在这里的人。你是唯一一个,而且你最好习惯如此。原谅我,朋友,我不会下船的。”“Land? Land is a ship too big for me. It’s a woman too beautiful; it’s a voyage too long, a perfume too strong. It’s a music I don’t know how to make. I could never get off this ship. At best, I can step off my life. After all, I don’t exist for anyone. You’re an exception, Max, you’re the only one who knows I’m here. You’re a minority, and you better get used to it. Forgive me, my friend, but I’m not getting off.”","link":"/6c9bcc36.html"},{"title":"travel hanghzou 2019.05.19","text":"杭城自旅小记 — 秋 Jack Liu2019.05.19己亥夏初余足行,时节竹帘壁岭顷。 雾引青峦过龙井,偶有惊雀嬉零星。 曲径邻岩苔缕兴,十里山茶步履轻。 云栖闻泉鸟争鸣,竹径临溪沥雨惊。 少时暂驻净思省,沐风携雨心亦明。 拍摄图片分享","link":"/aeef277b.html"}],"tags":[{"name":"AI","slug":"AI","link":"/tags/AI/"},{"name":"stable-diffusion-webui","slug":"stable-diffusion-webui","link":"/tags/stable-diffusion-webui/"},{"name":"clang","slug":"clang","link":"/tags/clang/"},{"name":"GUI","slug":"GUI","link":"/tags/GUI/"},{"name":"io","slug":"io","link":"/tags/io/"},{"name":"format","slug":"format","link":"/tags/format/"},{"name":"type","slug":"type","link":"/tags/type/"},{"name":"macro","slug":"macro","link":"/tags/macro/"},{"name":"ansi-lib","slug":"ansi-lib","link":"/tags/ansi-lib/"},{"name":"Cloud-Distributed","slug":"Cloud-Distributed","link":"/tags/Cloud-Distributed/"},{"name":"Distributed-Systems","slug":"Distributed-Systems","link":"/tags/Distributed-Systems/"},{"name":"mysql8.x","slug":"mysql8-x","link":"/tags/mysql8-x/"},{"name":"mysql8.0","slug":"mysql8-0","link":"/tags/mysql8-0/"},{"name":"mysql","slug":"mysql","link":"/tags/mysql/"},{"name":"utf8mb4","slug":"utf8mb4","link":"/tags/utf8mb4/"},{"name":"utf8mb4_0900_ai_ci","slug":"utf8mb4-0900-ai-ci","link":"/tags/utf8mb4-0900-ai-ci/"},{"name":"utf8mb4_general_ci","slug":"utf8mb4-general-ci","link":"/tags/utf8mb4-general-ci/"},{"name":"GIT","slug":"GIT","link":"/tags/GIT/"},{"name":"GPG","slug":"GPG","link":"/tags/GPG/"},{"name":"GPG2","slug":"GPG2","link":"/tags/GPG2/"},{"name":"JavaScript","slug":"JavaScript","link":"/tags/JavaScript/"},{"name":"JS","slug":"JS","link":"/tags/JS/"},{"name":"Go","slug":"Go","link":"/tags/Go/"},{"name":"go-pprof","slug":"go-pprof","link":"/tags/go-pprof/"},{"name":"GO方法值","slug":"GO方法值","link":"/tags/GO%E6%96%B9%E6%B3%95%E5%80%BC/"},{"name":"Go-chain-operation","slug":"Go-chain-operation","link":"/tags/Go-chain-operation/"},{"name":"func","slug":"func","link":"/tags/func/"},{"name":"go","slug":"go","link":"/tags/go/"},{"name":"Go Summary notes","slug":"Go-Summary-notes","link":"/tags/Go-Summary-notes/"},{"name":"goroutine","slug":"goroutine","link":"/tags/goroutine/"},{"name":"Go-init()","slug":"Go-init","link":"/tags/Go-init/"},{"name":"interface","slug":"interface","link":"/tags/interface/"},{"name":"JSON","slug":"JSON","link":"/tags/JSON/"},{"name":"Go(new,make,struct{})","slug":"Go-new-make-struct","link":"/tags/Go-new-make-struct/"},{"name":"Go(map)","slug":"Go-map","link":"/tags/Go-map/"},{"name":"Go null judge","slug":"Go-null-judge","link":"/tags/Go-null-judge/"},{"name":"pointer","slug":"pointer","link":"/tags/pointer/"},{"name":"Go-Polymorphism","slug":"Go-Polymorphism","link":"/tags/Go-Polymorphism/"},{"name":"Go-Printf","slug":"Go-Printf","link":"/tags/Go-Printf/"},{"name":"reflect反射","slug":"reflect反射","link":"/tags/reflect%E5%8F%8D%E5%B0%84/"},{"name":"slice切片本质","slug":"slice切片本质","link":"/tags/slice%E5%88%87%E7%89%87%E6%9C%AC%E8%B4%A8/"},{"name":"Go(string)","slug":"Go-string","link":"/tags/Go-string/"},{"name":"Go(Struct|Method|Receiver)","slug":"Go-Struct-Method-Receiver","link":"/tags/Go-Struct-Method-Receiver/"},{"name":"switch","slug":"switch","link":"/tags/switch/"},{"name":"struct","slug":"struct","link":"/tags/struct/"},{"name":"package time","slug":"package-time","link":"/tags/package-time/"},{"name":"type关键词总结","slug":"type关键词总结","link":"/tags/type%E5%85%B3%E9%94%AE%E8%AF%8D%E6%80%BB%E7%BB%93/"},{"name":"linux","slug":"linux","link":"/tags/linux/"},{"name":"centos7","slug":"centos7","link":"/tags/centos7/"},{"name":"systemd-service","slug":"systemd-service","link":"/tags/systemd-service/"},{"name":"OpenSSH","slug":"OpenSSH","link":"/tags/OpenSSH/"},{"name":"配置文件体系","slug":"配置文件体系","link":"/tags/%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%BD%93%E7%B3%BB/"},{"name":"chattr","slug":"chattr","link":"/tags/chattr/"},{"name":"firewalld","slug":"firewalld","link":"/tags/firewalld/"},{"name":"services","slug":"services","link":"/tags/services/"},{"name":"防火墙","slug":"防火墙","link":"/tags/%E9%98%B2%E7%81%AB%E5%A2%99/"},{"name":"debian","slug":"debian","link":"/tags/debian/"},{"name":"neofetch","slug":"neofetch","link":"/tags/neofetch/"},{"name":"rsync","slug":"rsync","link":"/tags/rsync/"},{"name":"banner","slug":"banner","link":"/tags/banner/"},{"name":"motd","slug":"motd","link":"/tags/motd/"},{"name":"rocky-linux","slug":"rocky-linux","link":"/tags/rocky-linux/"},{"name":"rocky-linux-tools","slug":"rocky-linux-tools","link":"/tags/rocky-linux-tools/"},{"name":"rocky","slug":"rocky","link":"/tags/rocky/"},{"name":"homebrew","slug":"homebrew","link":"/tags/homebrew/"},{"name":"macos","slug":"macos","link":"/tags/macos/"},{"name":"lua","slug":"lua","link":"/tags/lua/"},{"name":"hexo","slug":"hexo","link":"/tags/hexo/"},{"name":"CDN","slug":"CDN","link":"/tags/CDN/"},{"name":"nginx","slug":"nginx","link":"/tags/nginx/"},{"name":"Google","slug":"Google","link":"/tags/Google/"},{"name":"php","slug":"php","link":"/tags/php/"},{"name":"laravel","slug":"laravel","link":"/tags/laravel/"},{"name":"laravel-artisan","slug":"laravel-artisan","link":"/tags/laravel-artisan/"},{"name":"cli","slug":"cli","link":"/tags/cli/"},{"name":"VIM","slug":"VIM","link":"/tags/VIM/"},{"name":"VIM Author","slug":"VIM-Author","link":"/tags/VIM-Author/"},{"name":"Movie","slug":"Movie","link":"/tags/Movie/"},{"name":"Note The Legend of 1900","slug":"Note-The-Legend-of-1900","link":"/tags/Note-The-Legend-of-1900/"},{"name":"travel","slug":"travel","link":"/tags/travel/"},{"name":"daily","slug":"daily","link":"/tags/daily/"}],"categories":[{"name":"AI","slug":"AI","link":"/categories/AI/"},{"name":"clang","slug":"clang","link":"/categories/clang/"},{"name":"painting","slug":"AI/painting","link":"/categories/AI/painting/"},{"name":"Algorithm","slug":"Algorithm","link":"/categories/Algorithm/"},{"name":"distributed","slug":"distributed","link":"/categories/distributed/"},{"name":"Database","slug":"Database","link":"/categories/Database/"},{"name":"GIT","slug":"GIT","link":"/categories/GIT/"},{"name":"JavaScript","slug":"JavaScript","link":"/categories/JavaScript/"},{"name":"Go","slug":"Go","link":"/categories/Go/"},{"name":"Controlnet","slug":"AI/painting/Controlnet","link":"/categories/AI/painting/Controlnet/"},{"name":"Drawing","slug":"AI/painting/Controlnet/Drawing","link":"/categories/AI/painting/Controlnet/Drawing/"},{"name":"linux","slug":"linux","link":"/categories/linux/"},{"name":"macos","slug":"macos","link":"/categories/macos/"},{"name":"lua","slug":"lua","link":"/categories/lua/"},{"name":"reprinted-articles","slug":"reprinted-articles","link":"/categories/reprinted-articles/"},{"name":"php","slug":"php","link":"/categories/php/"},{"name":"history-of-programing","slug":"history-of-programing","link":"/categories/history-of-programing/"},{"name":"daily","slug":"daily","link":"/categories/daily/"},{"name":"centos","slug":"linux/centos","link":"/categories/linux/centos/"},{"name":"openssl","slug":"linux/openssl","link":"/categories/linux/openssl/"},{"name":"firewalld","slug":"linux/firewalld","link":"/categories/linux/firewalld/"},{"name":"debian","slug":"linux/debian","link":"/categories/linux/debian/"},{"name":"daily","slug":"history-of-programing/daily","link":"/categories/history-of-programing/daily/"},{"name":"note","slug":"daily/note","link":"/categories/daily/note/"}]}