编程语言学习指南
kotlin 基础
安装
homebrew
1 | brew install kotlin |
下载
交互式终端
1 | kotlinc-jvm |
HELLO WORLD
code
1 | // file: hello.kt |
compile
1 | kotlinc hello.kt -include-runtime -d hello.jar |
run
1 | java -jar hello.jar |
组织
文件
kotlin 源文件通常以.kt
作为扩展名。
包
1 | package base |
数据类型
类型
数字
类型 | 长度 |
---|---|
Double | 64 |
Float | 32 |
Long | 64 |
Int | 32 |
Short | 16 |
Byte | 8 |
字符
类型 | 长度 |
---|---|
Char | 字符 |
String | - |
布尔
类型 | 长度 |
---|---|
Boolean | - |
限定
修饰符 | 意图 | 目标 | 注意 |
---|---|---|---|
var | 变量 | 属性 | |
val | 不可变量 | 属性 | |
companion object | 静态 | - | |
final | 不可继承,默认值 | 类、属性、方法 | 不可修饰局部变量 |
open | 开放继承权限 | 类、属性、方法 | 不可修饰局部变量 |
const | 修饰可执行 宏替换 的常量 | 属性 | 只能修饰不可变量(val定义) |
注:
- 宏替换
- 宏变量 指编译时常量,宏替换指在编译阶段就会被替换掉
- 宏替换条件
- 使用 const 和 val 修饰的属性,如果进行拼接或者运算,被拼接的其他变量也要是宏变量
- 位于顶层或者是对象表达式的成员
- 初始值是基本数据类型
- 没有自定义的getter方法
常量
1 | // 10 进制 |
定义
1 | [final/open] [var/val] name : [Type] = ... |
数据结构
数组
列表
集合
映射
语法
程序结构
注释
1 | // 这是单行注释 |
条件控制
运算符
循环
判断
函数
1 | fun [funName](arga: [Type], argb: [Type], ...) : [Type] { |
类
特性
语法糖
空指针处理
函数式编程
泛型编程
参考
安卓基础
生命周期
状态
- INITIALIZED
- CREATED
- STARTED
- RESUMED
- DESTROYED
HOOK
- onCreate()
- onStart()
- onResume()
- onPause()
- onStop()
- onDestroy()
- onRestart()
启动模式
- standard
- singleTop
- 阻止创建栈顶Activity
- singleTask
- 阻止常见重复Activity
- singleInstance
- 使用独立栈
召回服务
简述
简单来讲,召回服务负责从内容池中, 拿取部分内容并返回,常用于搜索、推荐系统。
召回算法
通用召回
- 关键词
- 新热
- 分类
- 地域
- 多主题
协同过滤
- UserCF
- ItemCF
向量召回
- FM/FFM
模型召回
- TDM
文章
brpc
编译
1 | bash config_brpc.sh --headers="/path/to/deps/include/" --libs="/path/to/deps/lib/" --with-glog --with-thrift |
问题
NO 1
描述
1 | ERROR: something wrong with flag 'flagfile' in file '/home/wii/Git/cooking/c++/universal/third/build/gflags-2.2.2/src/gflags.cc'. One possibility: file '/home/wii/Git/cooking/c++/universal/third/build/gflags-2.2.2/src/gflags.cc' is being linked both statically and dynamically into this executable. |
解决
gflags静态库和共享库同时存在导致。gflags 是选择手动编译,在编译时为cmake指定-DBUILD_SHARED_LIBS=1
只编译共享库,如果是使用命令安装,可以尝试先移除/usr/local/lib/libgflag.a
和 /usr/local/lib/libgflag_nothread.a
。
gflags
编译
1 | mkdir build && cd build |
更多参考这里。
CMake
提取Namespace
1 | execute_process( |
版本信息
CMakeLists.txt 添加版本定义
1 | execute_process( |
设置版本信息
1 | int main(int argc, char *argv[]) { |
二进制程序打印版本信息
1 | ./bin/{app} --version |
使用
类型
基于gflags的设计哲学,不提供复杂的数据类型,可自行解析。
- DEFINE_bool
- DEFINE_int32
- DEFINE_int64
- DEFINE_uint64
- DEFINE_double
- DEFINE_string
定义
示例
1 |
|
说明
可在任意文件中定义flag,但只能定义一次(只能 DEFINE 一次,但是可 DECLARE 多次)。如果需要访问位于多个源文件中的glfag,那么在其他文件中使用 DECLARE。最好,在foo.cc
中使用 DEFINE 定义,在foo.h
中使用 DECLARE 声明,那么只要在代码中添加 #include <foo.h>
就可以使用该flag。
访问
1 | // 修改 |
声明检查
1 | static bool ValidatePort(const char* flagname, int32 value) { |
在全局初始化时(紧接着DEFINE_int32定义flag)注册检查方法,可以保证在运行main()
函数解析命令号之前执行校验。上面的代码,使用DEFINE_validator
宏指令调用 RegisterFlagValidator
方法,如果注册成功,返回true;如果第一个参数不是命令行标记或者该标记注册了其他校验,则返回false;返回值以<flag>_validator_registered
命名作为全局变量供访问。
解析标记
1 | gflags::ParseCommandLineFlags(&argc, &argv, true); |
通常,改代码唯有main()
的开始。argc
和 argv
是传入main()
方法的准确参数,该例程可能会修改他们。最后的布尔参数用于指示是否从argc
中删除标记(flags)以及其参数(arguments),并同步修改argv
。如果为true,在该方法调用之后,argv只会保存命令行参数(commandline arguments),而不是命令行标记(glags)。如果为false,那么 ParseCommandLineFlags 不会修改 argc,但是会对argv中的参数重排序,使得所有的标记在最开始。比如,"/bin/foo" "arg1" "-q" "arg2"
,方法会重排序 argv 为 "/bin/foo" "-q" "arg1" "arg2"
,ParseCommandLineFlags 返回 argv 中第一个参数的索引,也即标记(flag)的后面的索引(在刚才的例子中,返回2,因为 argv[2] 指向第一个参数 arg1)。
注,命令行标记(commandline glags)形如 -e -q
,命令行参数(commandline arguments)形如 arg1 arg2
。
在命令行设置标记
1 | foo --nobig_menu -languages="chinese,japanese,korean" ... |
当运行 ParseCommandLineFlags 时,会设置 FLAGS_big_menu = false; FLAGS_languages = "chinese,japanese,korean"
。通过在标记前面添加no
,为标记设置为 false 值。以下方式均可设置 languages 值。
1 | app_containing_foo --languages="chinese,japanese,korean" |
布尔型值稍有不同。
1 | app_containing_foo --big_menu |
尽管有很多方式灵活设置标记值,但是推荐使用统一的格式 --variable=value
,对于布尔值使用 --variable/--novariable
。
注意
- 如果在命令行中指定了标记,但是没有在程序中定义(使用DEFINE),将会导致致命错误。可以通过添加
--undefok
来屏蔽该异常 - 在 getopt 中,
--
标记会终止标记解析,所以foo -f1 1 -- -f2 2
,中,f1
是标记,f2
不是 - 如果标记被指定多次,后面的值覆盖前面的,即最后一次定义有效
- 不像 getopt 库那样支持 单字母同义词,比如
-h
(和--help
同义),同样的也不支持组合标记,如ls -la
修改默认值
有时候标记位于依赖库中,如果只想在一个程序中修改默认值,其他应用不变。可在 main()
方法中赋值新值,在调用 ParseCommandLineFlags
之前。
1 | DECLARE_bool(lib_verbose); // mylib has a lib_verbose flag, default is false |
这种情况下,用户依然可以在命令行中指定标记值,但是如果不指定,则使用新的默认值。
特殊标记
-
--undefok=flagname,flagname,...
- 对于指定的这些标记名称,用于阻止当命令行指定标记但在程序中未定义导致的异常退出
-
--fromenv
-
--fromenv=foo,bar
-
从环境变量中读取值,如果环境变量中未定义,则会导致致命异常
1
2
3
4
5
6export FLAGS_foo=xxx; export FLAGS_bar=yyy # sh
setenv FLAGS_foo xxx; setenv FLAGS_bar yyy # tcsh
等同于
--foo=xxx, --bar=yyy -
-
--tryfromenv
- 类似于
--fromenv
,区别是如果环境变量中未定义标记,不会导致异常
- 类似于
-
--flagfile
-
--flagfile=f
-
从文件读取参数定义,文件内容为标记定义列表,每行一个
-
与命令行不同的是,需要等号将标记和参数值分开(命令行参数有多种设置方式,可不加等号)
1
2
3
4
5
6
7示例文件 /tmp/myflags:
--nobig_menus
--languages=english,french
两种等价方式
./myapp --foo --nobig_menus --languages=english,french --bar # --foo 和 --bar 泛指其他参数
./myapp --foo --flagfile=/tmp/myflags --bar-
注意:flagfiles方式,一些错误会默认禁止。特别的,未识别的标记名异常默认忽略(这在命令行设置方式下,需要显式使用
--undefok
指定),以及未指定值的异常(比如在flagfile中只定义--languages
,而不指定参数) -
通常的 flagfile 比示例要复杂:一系列文件名,每行一个,每个后面紧接着一系列标记,每行一个,根据需要重复多次。flagfile中的文件名可用通配符,比如
*
和?
,仅当当前程序的名称和flagfile文件中filenames中的一个匹配时,才会处理其挨着的标记 -
以
#
开头的行会被忽略 -
空白行及前置空白符会被忽略
-
可在 flagfile 中使用
--flagfile
指定其他 flagfile -
标记总是以期望的方式处理,首先从检查命令行参数开始,如果遇到 flagfile ,则处理其内容,然后继续处理后续标记
-
1 | 示例文件 gflags_test.cmd |
其他
移除帮助信息
可减少编译源文件时的帮助信息,及二进制文件大小,或一些安全相关的隐患。
1 |
问题
NO 1
描述
1 | ERROR: something wrong with flag 'flagfile' in file '/home/wii/Git/cooking/c++/universal/third/build/gflags-2.2.2/src/gflags.cc'. One possibility: file '/home/wii/Git/cooking/c++/universal/third/build/gflags-2.2.2/src/gflags.cc' is being linked both statically and dynamically into this executable. |
解决
在编译gflags时,使用 cmake 参数 -DBUILD_SHARED_LIBS=1
指定只编译共享库。
参考
2021 todo list
事项
- 早睡早起,每天12点前睡觉,保持七个小时睡眠
- 每天2L水
- 徒步(10公里+) / 骑行(20公里+)8次
- [ ] 体重控制在140以下
- 读25本书,8本技术书
- 上线博客站点,文章 50+
- 掌握特征工程及模型训练
- 精读一种训练框架源码(tensorflow、xdl、paddlepaddle)
- 熟读SpringMVC源码
- 熟读一种微服务框架(dubbo、Spring Cloud)
- 熟读一种DB源码(RocksDB、Redis、HBase)
读书
文学
- [ ] 百年孤独
- [x] 人生海海
经济学
- [ ] 贫穷的本质
- [ ] 经济学原理
- [ ] 结构性改革
心理学
- [x] 被讨厌的勇气
- [ ] 反脆弱
传记
- [x] 只有偏执狂才能生存
- [ ] 忏悔录
互联网
- [ ] 浪潮之巅
技术
- [x] 设计模式(Head First)
- [ ] 分布式服务架构原理、设计与实战
效率
- [ ] 高效能人士的7个习惯
成长
- [ ] 想哲学家一样生活
- [ ] 沉思录
文章
算法
效率
cmake/makefile flags
规约
编译源文件
1 | (CC) $(CPPFLAGS) $(CFLAGS) example.c -c -o example.o # -c: 编译,不执行链接操作 |
链接
1 | (CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) example.c -o example # -o: 指定输出文件名字 |
命令
命令 | 说明 |
---|---|
CC | C 编译器 |
CXX | C++ 编译器 |
CPP | C / C++ 预编译器,通常是 “$(CC) -E” |
示例
1 | export CC=/usr/local/bin/gcc-7 |
变量
变量 | 含义 | 示例 |
---|---|---|
CFLAGS | C 编译器选项 | |
CXXFLAGS | C++ 编译器选项 | |
CPPFLAGS | C/C++ 预处理器的命令行参数 | |
LDFLAGS | 链接参数 | |
LD_LIBRARY_PATH | 运行时动态链接库查找路径 | |
LIBRARY_PATH | 编译时链接库查找路径 | /usr/lib |
C_INCLUDE_PATH | 头文件查找路径 | |
CPLUS_INCLUDE_PATH | C++ 头文件查找路径 | |
OBJC_INCLUDE_PATH | ObjectiveC 头文件查找路径 | |
CPATH | C/C++/ObjectiveC 头文件默认查找路径,多个路径使用 : 分隔,比如 .:/root/include |
|
DYLD_LIBRARY_PATH | Mac OS 动态链接库查找路径 |
参数
参数 | 说明 | 示例 |
---|---|---|
c | 编译 | -c |
o | 输出文件名称 | -o |
g | 添加调试信息 | -g |
l(小写L) | 链接标准库 | -lz |
L | 指定库搜索路径 | -L/user/local/lib |
I(大写i) | 指定头文件搜索路径 | -I/user/local/include |
static | 在支持动态链接的系统中,该参数覆盖-pie,并阻止链接共享库 | -static |
shared | 生成可被链接的共享对象 | -shared |
PIC / pic | 使用位置无关代码创建对象文件,创建共享库时需指定 | -fpic / -fPIC |
说明
-llibrary
/-l library
链接时,搜索指定库,优先使用共享库,除非指定-static
参数
cmake - libraries
gflags
官方文档。
1 | # 查找、链接库 |
cmake 使用
示例
CMakeLists.txt
1 | mkdir cmake-project |
Code
1 | mkdir src && vim src/main.cpp |
Config
1 | cmake_minimum_required(VERSION 3.10) |
Build
1 | mkdir build && cd build |
Run
1 | ./Tutorial |
语法示例
1 | cmake_minimum_required(VERSION 2.8) |
完整示例
1 | cmake_minimum_required(VERSION 2.8) |
编译
1 | mkdir build && cd build |
macro
1 | macro(AddLibrary MODULE) |
1 | macro(AddLibraryV2 MODULE) |