01-Rust基本语法

rust 基本语法

1: 变量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
   fn f0(){
    println!("--------变量-----------");
    let a=12;
    let b =100;
    println!("a is {1},b is {0}",a,b);
    println!("{}","{}");
    println!("add(): {}",add(a, b));

    // 变量重新赋值
    let mut c=5;
    println!("c is  首次声明:{0}",c);
    c = 66;
    println!("c is  重新赋值:{0}",c);

    // 变量重新绑定,变量的值可以"重新绑定",但在"重新绑定"以前不能私自被改变
    // 重影(Shadowing)
    let a :i32=11;
    println!("a is重新绑定{}",a) ;


    // 常量
    const D: i32 = 99;
    println!("常量D:{0}",D);

    //
    let a:u64 =123;
    println!("a is重新绑定{}",a);

    // 重影(Shadowing)
    // 重影与可变变量的赋值不是一个概念,重影是指用同一个名字重新代表另一个
    // 变量实体,其类型、可变属性和值都可以变化。但可变变量赋值仅能发生值的变化。
    let x =5;
    let x=x+1;
    let x=x*2;
    println!("the value of x is:{}",x);
}

// rust 不支持自动返回值类型判断
// 如果没有明确函数返回值类型,函数将被认为是"纯过程“,不允许产生返回值,return不能有返回值表达式
fn add(a:i32,b:i32)->i32{
    return a+b
}

2: float 类型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
fn f1(){
    println!("--------float类型-----------");

    let x =2.0; //f64
    let y: f32 = 3.0;//f32

    println!("x is {0},y is {1}",x,y);

    let mut ok  =true;
    println!("ok is {}",ok);
    ok=false;
    println!("ok is {}",ok);
}

3: 复合类型:tuple 元组,arrary,slice

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
fn f2(){
    println!("--------复合类型:tuple,array,slice-----------");
    // 复合类型
    // tuple元组 ,用一对()包括的一组数据,可以包含不同种类的数据
    let tup:(i32,f64,u8,char) = (10,9.9,5,'a');
    println!("元组 tup: {} {} {} {}",tup.0,tup.1,tup.2,tup.3);
    println!("元组 tup: {:?}",tup);
    println!("元组 tup: {:?}",tup.3);

    // 数组,用[]包含相同类型的数据
    let a = [1,2,3,4,5]; //a是一个长度为5的数组
    let b = ["go","rust","java"];//b是一个长度是4的字符串数组
    let c: [i32;5] = [1,2,3,4,5];//c是一个长度是5,类型是i32的数组

    println!("数组a 的a[0]元素 : {}",a[0]);
    println!("数组b 的元素: {:?}",b);
    println!("数组c 是长度是{}类型是{}的数组:{:?}",c.len(),"i32",c);

    // slice 切片是对数据值的部分引用
    // 1:字符串切片
    let s = String::from("broadcast");
    let part1 = &s[..5];
    let part2 =&s[5..];
    // 2:对象被部分引用,禁止更改值
    // s.push_str(",aod");//TODO 错误:s被部分引用,禁止修改其值
    println!("字符串切片:{}={}+{}",s,part1,part2);

    // 3:非字符串切片
    // let a=[1,2,3,4,5];
    let patr3 =&a[1..3];
    println!("{}",patr3[0]);
    println!("非字符串切片part3:{:?}",patr3);
}

4: 字符串

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
    fn f3(){
    // rust中的字符串通常指 &str, String
    // rust内部的字符串默认是使用utf-8编码格式的(String和&str),
    // 而内置的char类型是4字节长度的,存储的是Unicode字符,所以Rust里面的字符串不能视为char类型的数组,而更接近u8类型的数组


    // 分的比较清.简单的可以理解为: &str 是分配在栈上, String分配在堆上.
    println!();
    println!();
    println!("--------str String  初始化 ...-----------");

    let mut a = String::from("food"); // 在堆上分配内存
    println!("as_ptr()打印堆内存的地址: {:p}", a.as_ptr()); // 打印堆内存的地址
    println!("&a 打印变量a 在栈上的地址: {:p}", &a); // 打印变量a 在栈上的地址
    println!("{} {}", a.len(),a.capacity()); // 字符串在堆内存中的字节长度, 不是字符长度!!!
    a.reserve(10); // 增加堆的内存长度
    println!("{} {}",a.len(), a.capacity()); // 总字节容量
    // 切片
    let e = &a[1..3];
    println!("切片 e: {:?},len是:{}",e,e.len());


    let str: String = String::new(); // 创建空字符串
    println!("str: {} , len: {}, cap: {}",str,str.len(),str.capacity());
    let str2: String = String::from("hello rust"); // 创建堆内存
    println!("str2: {}",str2);
    let str3: String = String::with_capacity(20); // 创建20字节的空堆内存
    println!("str3: {}, cap: {}",str3,str3.capacity());
    let str4: &'static str = "the tao of rust"; // 静态变量
    println!("str4: {}",str4);
    let str5: String = str4.chars().filter(|c| !c.is_whitespace()).collect(); // .chars() 返回 各字符
    println!("str5: {}",str5);
    let str6: String = str4.to_owned(); // 与 to_string() 基本相同
    println!("str6: {}",str6);
    let str7: String = str4.to_string();
    println!("str7: {}",str7);
    let str: &str = &str4[11..15]; // 取静态字符串的部分内容, 学名 切片 (slice)
    println!("str: {}",str);


    println!("--------字符串增加 ...-----------");
    let mut hello = String::from("hello,");
    hello.push('R');
    hello.push_str("-Rust");
    hello.insert_str(2,"-");
    println!("hello字符串增加1: {}",hello);
    let suffix =String::from("-rust");
    hello=hello+&suffix; //NOTE: +后面的对象要带&
    println!("hello字符串增加2: {}",hello);


    println!("--------字符串遍历 ...-----------");
    let s = String::from("good evening...");
    let s: String = s.chars().enumerate().map(|(i,c)|{
        if i%2 == 0{
            c.to_lowercase().to_string()
        }else{
            c.to_uppercase().to_string()
        }
    }).collect();
    println!("s遍历: {}",s);


    println!("--------字符串位置查询以及子串...-----------");
}

5: 条件分支

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
fn f4(){
    println!("--------条件判断语句...-----------");
    // if
    let a = 12;
    let b;
    if a>0{
        b=1;
    }else if a<0{
        b=-1;
    }else{
        b=0;
    }

    println!("b is {}",b);


    // 三元条件表达式 (A?B:C)
    let a=3;
    let number=if a > 0 {1} else {-1};
    println!("number is {}",number);

    // match  多条件分支
    // TODO match 除了能够对enum类型进行分支选择以外,还可以对整数、浮点数、字符和字符串切片引用(&str)类型的数据进行分支选择。
    // TODO 其中,浮点数类型被分支选择虽然合法,但不推荐这样使用,因为精度问题可能会导致分支错误。
    let n ="abc";
    match n{
        "abc"=>println!("Yes"),
        _=>{},
    }

    // TODO: if let语句
    /*
    if let 匹配值 = 源变量 {
        语句块
    }else{

    }
    */
    enum Book{
        Papery(u32),
        Electronic(String)
    }
    let book=Book::Electronic(String::from("url"));
    if let Book::Papery(index)=book{
            println!("Papery:{}",index);
    }else{
            println!("not papery book");
    }
}

6: 循环语句

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
fn f5(){
    println!("--------循环语句...-----------");
    let mut i: i32;
    i=0;
    while i<4{
        println!("i:{}",i);
        i=i+1;
    }

    let arr=[10,20,30,40,50];
    for i in arr.iter(){ //迭代器 iter(),iter_num()
        println!("for in iter() 遍历: {}",i);
    }

    for i in 0..arr.len(){
        println!("for in 下标 遍历: {}",i);
    }
}

7: 所有权 ownership

// rust 所有权 // 1: Rust 中的每一个值都有一个变量,称其为所有者; // 2:一次只能有一个所有者; // 3:当所有者不在程序的运行范围时,该值将被删除。

01-win10安装Rust步骤

1: 首先配置环境变量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 修改为国内镜像
#    由于rustup的官方服务器在国外,如果直接按照rust官网的方式安装,
#    非常慢且容易fail
RUSTUP_DIST_SERVER=http://mirrors.ustc.edu.cn/rust-static
RUSTUP_UPDATE_ROOT=http://mirrors.ustc.edu.cn/rust-static/rustup


# rust 安装路径
CARGO_HOME:D:\Program Files\RUST\.cargo
RUSTUP_HOME:D:\Program Files\RUST\.rustup

#
~/.cargo/bin 添加到PATH

# 下载安装racer (rust代码补全程序)
# 如果不成功,先将rustup更新成nightly版本,再进行下载:
rustup install nightly
cargo +nightly install racer

2:按照官网方式进行安装

地址:https://www.rust-lang.org/zh-CN/tools/install

01-Linux Manual

1: 文件

1.1 查看文件内容

1.1.1 head

显示文件的头部内容,默认前 10 行

01-Go格式化占位符汇总

Go格式化占位符汇总

1:占位符 placeholder

1.1 通用占位符 placeholder

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
// %v: 值的默认格式表示
fmt.Printf("%v\n", 100) //100

// %+v: 类似%v,但输出结构体时会添加字段名
o := struct{ name string }{"tim"}
fmt.Printf("%+v\n", o)  //{name:tim}

// %#v: 值的 Go 语法表示
o := struct{ name string }{"tim"}
fmt.Printf("%#v\n", o)  //struct { name string }{name:"tim"}

// %T: 打印值的类型
o := struct{ name string }{"tim"}
fmt.Printf("%T\n", o) //struct { name string }

// %%: 打印%百分号
fmt.Printf("100%%\n")  //100%

// %t: 布尔型 boolean(true,flase)
t := true
fmt.Printf("value: %t", t)

1.2 整形占位符 placeholder

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// %b 整形二进制
fmt.Printf("%b\n", 65)//1000001

// %c 该值对应的unicode码值
fmt.Printf("%c\n", 65)//A

// %d 表示为十进制
fmt.Printf("%d\n", 65)//65

// %o 表示为八进制
fmt.Printf("%o\n", 65)//101

// %x 表示为十六进制,使用1-f
fmt.Printf("%x\n", 65)//41

// %X 表示为十六进制,使用A-F
fmt.Printf("%X\n", 65)//41

// %U 表示为Unicode格式:U+1234,等价于”U+%04X”
fmt.Printf("%U\n", 65) // U+0041

// %q 该值对应的单引号括起来的go语法字符字面值必要时会采用安全的转义表示
fmt.Printf("%q\n", 65)//'A'

1.3 浮点数与复数 placeholder

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
f := 12.34
// 浮点型,有小数部分但无指数部分
fmt.Printf("%f\n", f) // 12.340000
// 小数点后2位小数
fmt.Printf("%.2f\n", f) // 12.34
fmt.Printf("%F\n", f)   // 12.340000
// 无小数部分、二进制指数的科学计数法
fmt.Printf("%b\n", f) // 6946802425218990p-49
// 科学计数法
fmt.Printf("%e\n", f) // 1.234000e+01
// 根据实际情况采用%e或%f格式
fmt.Printf("%g\n", f) // 12.34
// 根据实际情况采用%E或%F格式
fmt.Printf("%G\n", f) // 12.34

1.4 字符串和[]byte placeholder

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// %s  直接输出字符串或者[]byte
fmt.Printf("%s\n", "tim") //tim

// %q 该值对应的双引号括起来的go语法字符串字面值,必要时会采用安全的转义表示
fmt.Printf("%q\n", "tim") //"tim"

// %x 每个字节用两字符十六进制数表示(使用1-f)
fmt.Printf("%x\n", "tim") //74696d

// %X 每个字节用两字符十六进制数表示(使用1-F)
fmt.Printf("%X\n", "tim") //74696D

1.5 pointer

1
2
3
4
// %p 表示为十六进制,并加上前导的0x
t := []int{1}
fmt.Printf("value: %p", t)
// value: 0x14000190008

1.6 宽度标识符 placeholder

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// %f 默认宽度,默认精度
v := 92873.2309837
fmt.Printf("value: %f\n", v) // value: 92873.230984

// %9f 宽度9,默认精度
fmt.Printf("value: %9f\n", v) // value: 92873.230984

// %9.f  宽度9,精度0
fmt.Printf("value: %9.f\n", v) // value:     92873

// %9.2f 宽度9,精度2
fmt.Printf("value: %9.2f\n", v) // value:  92873.23

1.7 其他 flag

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
'+'
总是输出数值的正负号%q%+q会生成全部是ASCII字符的输出通过转义
v := 92873.2309837
fmt.Printf("value: %+f", v) // value: +92873.230984

' '
对数值正数前加空格而负数前加负号对字符串采用%x或%X时% x或% X会给各打印的字节之间加空格
v := 92873.2309837
fmt.Printf("value: %+f\n", v) // value: +92873.230984
fmt.Printf("value: % f\n", v) // value:  92873.230984

'0'
使用0而不是空格填充对于数值类型会把填充的0放在正负号后面
fmt.Printf("value: %07.2f\n", v) // value: 92873.23

'#'
八进制数前加0%#o),十六进制数前加0x%#x或0X%#X),指针去掉前面的0x%#p%q%#q),%U%#U会输出空格和单引号括起来的go字面值

'-'
在输出右边填充空白而不是默认的左边即从默认的右对齐切换为左对齐
v := 101.35345345
fmt.Printf("value: %-3.1f\n", v) // value: 101.4

2:go 占位符

通用占位符 placeholder

01-Go开发效率神器汇总

Table of Contents

1:开发工具

1: sql2go sql 语句转换为 Go 结构体,使用 ddl。 http://stming.cn/tool/sql2go.html

2: json2go 将 json 格式转为 Go struct https://mholt.github.io/json-to-go/

3: toml2go 将编码后的 toml 文本转为 Go struct https://xuri.me/toml-to-go/

4: curl2go 将 curl 命令转为 go 代码 https://mholt.github.io/curl-to-go/

5: msql 转 ES sql 语句转换为 ES 语句. http://www.ischoolbar.com/EsParser/

02-Go常用库积累

1:日志库

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
https://github.com/hunterhug/golog

https://github.com/uber-go/zap
https://github.com/rs/zerolog
https://github.com/Sirupsen/logrus


// 日志滚动包
https://github.com/natefinch/lumberjack


// 日志分析和查询平台
https://github.com/clickvisual/clickvisual

2:配置库

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// viper 兼容 json,toml,yaml,hcl 等格式的配置库.
https://github.com/spf13/viper

// configor Golang Configuration tool that support YAML, JSON, TOML, Shell Environment
https://github.com/jinzhu/configor



// env
https://github.com/caarlos0/env

// Support for JSON, TOML, YAML, env, command line, file, S3 etc. Alternative to viper.
https://github.com/knadh/koanf

// A dead simple configuration manager for Go applications.
https://github.com/tucnak/store

3:存储相关

1
2
3
4
5
mysql: https://github.com/go-xorm/xorm
es: https://github.com/elastic/elasticsearch
redis: https://github.com/gomodule/redigo
mongo: https://github.com/mongodb/mongo-go-driver
kafka: https://github.com/Shopify/sarama

4:数据结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
https://github.com/emirpasic/gods (go数据结构,sets,lists,stacks,maps.trees,queues ...)

// mapstructure
https://github.com/mitchellh/mapstructure (map和struct转换)


// json
https://github.com/liu-cn/json-filter

// 延迟队列(delay queue)
github.com/morikuni/go-dqueue

// 无锁队列
https://github.com/lppgo/go-lockfree-queue


// map
https://github.com/cornelk/hashmap (线程安全,lockfree hashmap)
https://github.com/alphadose/haxmap (Fastest and most memory efficient golang concurrent hashmap)
https://github.com/orcaman/concurrent-map


// xmap

5:CLI 命令行

1
2
https://github.com/spf13/cobra
https://github.com/urfave/cli/

6:web 框架

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// gin
https://github.com/JGLTechnologies/gin-rate-limit
https://github.com/appleboy/gin-jwt
// echo
// beego
// goframe
// firber

gocondor [A golang framework for building modern APIs]
// https://github.com/gocondor/gocondor
...

7:RPC 和微服务

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// grpc
https://github.com/grpc/grpc-go

// micro
https://github.com/asim/go-micro

// kratos
https://go-kratos.dev/docs/getting-started/usage

//
https://github.com/air-go/rpc

7.1 Remote Procedure Call

7.1.1 原生 RPC

7.1.2 GRPC

7.1.2.1 GRPC 安装

7.1.2.2 GRPC 使用

7.1.2.3 grpc-middleware

1
https://github.com/grpc-ecosystem/go-grpc-middleware

7.1.2.4 GRPC 测试

01-加密技术,数字签名,数字证书

. Table of Contents

1:前言 Perface

  1. 什么是数字签名,数字签名的作用是什么?
  2. 什么是数字证书,数字证书解决了什么问题?
  3. 什么是对称加密和对称加密,区别是什么?
  4. 非对称加密公私钥都可加密,那什么时候用用公钥加密,什么时候用私钥加密?
  5. 为什么要对数据的摘要进行签名,而不是计算原始数据的数字签名?

加密 encrypt 解密 decrypt