理解 regexp

作者注: 我的文章都很片面,是我按着自己的理解记录的,很可能有错误喔~ 请谨慎参考!请谨慎参考!请谨慎参考! 也非常非常希望您在发现错误了之后联系我, qq:281127500 匹配规则 从左到右 从外到内 分组匹配 组内,也就是说一个括号内的匹配,对于整个正则来讲,它只匹配一次。 举个例子: 正则 regexp.MustComplie(`;\s(?i:(m1|m2|m3)(\s*\w*)[\s\)])`) 待匹配字符串 "-#; m1 BJM); m2 SKC ; m3 FEF){}" 匹配结果 ​ 可以看到,全匹配 匹配到三组,并且,每一组全匹配里面的 分组匹配 的每一组匹配(略微有点绕口哈~你品你细品)都只匹配一次。这个不是嵌套分组,感觉可能没那么明显,那么下面来一组嵌套分组的例子 可以看到,正则里面有三个分组(那个(?i:)结构是不区分大小写的意思,不要误认为是分组),其中两个是嵌套关系(分组2和分组3),首先是外层(分组2)匹配到“HM NOTE 1”,接着匹配内层分组(分组3),内层分组被外层分组重复利用了多次,但是只能匹配到一次,保存的是最后一次匹配到的值,所以是"hhh"。 假如没有了外层分组, 如下图,可以看到,内层匹配到的也是最后一次保存到的匹配到的值,即"hhh"。 golang 匹配汉字 正则: [\p{Han}] 可以匹配到任何一个汉字

完整性约束

一、完整性约束的概念 ​ 保证授权用户对数据库所做的修改不会破坏数据的一致性。 ​ 因此,完整性约束 防止的是对数据的意外破坏。 二、完整性约束分为三类,包括: ​ \1. 域完整性 :是指给定列的取值范围(即输入的有效性) ​ \2. 实体完整性 :规定表中的每一行在表中是唯一的一个实体(实体就是一条记录) ​ \3. 参照完整性 :保持主外键之间的参照规则。它保证的是表之前数据的一致性,防止了数据丢失或无意义的数据在数据库中扩散。 ​ 4.用户定义完整性:不同的关系数据库系统根据其应用环境的不同,往往还需要一些特殊的约束条件。用户定义的完整性是针对某个特定关系数据库的约束条件,它反映某一具体应用必须满足的语义要求。(就是根据特定的业务,用户自定义的规则) 三、完整性约束的类型 ​ \1. 主键约束(PRIMARY KEY):要求主键列 数据唯一,并且不允许为空,PRIMARY KEY = UNIQUE + NOT NULL。主键可以包含表的一列或多列。你定义的主键包含多列时,你只能在表级定义。 ​ # 在表级定义主键约束 ​ CREATE TABLE student ( ​ sno NUMBER(3), ​ same VARCHAR2(15), ​ gender CHAR(3) DEFAULT ‘男’, ​ age NUMBER(2), ​ CONSTRAINTS pk_student PRIMARY KEY (sno,sname) ​ ); ​ # 在列级定义主键约束 ​ CREATE TABLE student (

Goroutine 执行顺序

package main import ( "fmt" ) func sum(s []int,c chan int){ num:=0 for _,v:=range s { num+=v } c<-num } func main(){ s:=[]int{7,2,8,-9,4,0} c:=make(chan int,0) go sum(s[len(s)/2:],c) go sum(s[:len(s)/2],c) //y,x:=<-c,<-c x:=<-c y:=<-c fmt.Println(x,y,x+y) } 输出: 17 -5 12 值得我好奇的是,这个输出顺序是固定的,按我之前的理解来讲,我认为这个顺序应该是变化的,就是可能先输出-5,接着再输出17,也可能先输出17,再输出-5这种顺序,我反复运行好多次,结果很出乎我的意料/ 下面来解释一下原因(摘自网络) go 关键字只是一个语法糖,可以认为 go func() 只是创建了一个 待被执行任务(G),for 循环只能保证三个任务的创建顺序是 G(a) -> G(b) -> G(c),但三个任务很可能会被分配到不同的cpu core上执行(go 的运行时调度器来分配)。所以三个任务的执行顺序是不确定的。 但是比较奇妙的是,一般情况下「在同一个 goroutine 中创建的多个任务」中最后创建那个任务最可能先被执行。原因的话就要看 go 的实现细节了:简单来说,同一 goroutine 中三个任务被创建后 理论上会按顺序 被放在同一个任务队列,但实际上最后那个任务会被放在 next(下一个要被执行的任务的意思)的位置,所以优先级最高,最可能先被执行。剩下的两个任务如果 go 运行时调度器发现有空闲的 core,就会把任务偷走点,让别的 core 执行,这样才能充分利用多核,提高并发能力。

构建容器

根据 dockerfile 文件构建镜像,进而构建容器 构建镜像 先写好一个dockerfile文件,然后命令行执行: $ docker image build --file <path_to_dockerfile> --tag <repository>:<tag> . 通常不会加 --file 参数,就直接: $ docker image --tag <repostory>:<tag> . 注意最后面这个 · 表示此命令在当前文件夹中构建镜像 构建容器 启动容器 $ docker container run -d --name <container_name> -p <container_port>:<宿主机port> <repostory>:<镜像tag> -v 停止/删除 容器 $ docker container stop <container1_tag> <container2_tag> $ docker container <container1_tag> <container2_tag> 使用基础镜像去构建容器 不推荐这种做法 拉取基础镜像 $ docker image pull <image_name>:<版本号,一般latest> $ docker image pull ubuntu:latest 使用镜像容器 $ docker container run -it --name <container_name> <image_name> /bin/sh $ docker container run -it --name ubuntu-test ubuntu /bin/sh 保存镜像文件 $ docker container commit <container_name> <repository>:<tag> $ docker container commit ubuntu-test local:broken $ docker container save -o <file_name.

细说三次握手与四次挥手

seq, ack, fin seq: 确认序列 ack: 确认包 fin: 断开连接包 三次握手 客户端先发送 SYN=x 请求建立连接 服务器返回 ACK=x+1,SYN=Y 客户端再回复 ACK=Y+1 建立连接成功 为什么是三次握手? 假设 client 端向 server 端发送了一个请求报文(没有丢失的报文),但是不幸在网络节点中被滞留了,以至于延误了,直到 client 端释放了该连接之后才抵达 server 端, 如果在没有第三次握手的前提下,那么 server 端会直接建立连接成功,但是 client 端这个连接对于它来讲已经失效了,所以它不会用这个连接去跟 server 进行沟通了,也就是说它不会再发任何数据给 server 端了,那么这样导致的就是呢一次连接的浪费 如果有第三次握手呢,server 端对 client 传过来的这个报文请求会向其发送 ACK 和 SYN,等待 client 回复 ACK 确认消息,该连接才会被认为是有效的,这样一来,就不会出现浪费资源的情况。 从而证明三次握手是必要的! 第二次握手证明 client=>server 是没问题的 第三次握手证明 server=>client 是没问题的 TCP 是全双工通信的,由于网络通信是不可靠的,所以通过三次握手可以「最低限度」的确认全双工通信通道 四次挥手 想要断开连接的一方 向 对方 发送一个 FIN 数据包,对方收到之后回复一个 ACK ,在间隔一段时间之后,再发送 FIN, 然后 主动断开的一方 回复 对方 一个 ACK