普拉多VX

人生一路,不问来时,不知归期

0%

Time标准库

golang 时间显示和格式化等等操作主要是使用time包,日历的计算采用的是公历时间。

标准库用法

1
2
3
4
Now()
Unix()
Date()
UnixNano()

1.显示当前时间,返回的是Time类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main

import (
"fmt"
"time"
)


func main(){

now := time.Now() //时间对象
fmt.Println(now)

}

输出结果为

1
2020-05-15 14:55:29.0136499 +0800 CST m=+0.004986301

2.通过Time对象获取当前时间的年、月、日 小时、分钟等

1
2
3
4
5
6
7
now := time.Now() //时间对象
year := now.Year() //年
month := now.Month() //月
day := now.Day() //日
hour := now.Hour() //小时
minute := now.Minute() //分钟
second := now.Second() //秒

3.Sleep沉睡

1
time.Sleep(time.Second * 1)  //沉睡1秒

时间戳

1.获取当前的时间戳,从1970 01 01到现在的时间的秒数

1
2
3
4
timeStamp1 := now.Unix()
timeStamp2 := now.UnixNano()
fmt.Println(timeStamp1) //当前世间戳
fmt.Println(timeStamp2) //当前世间戳微秒,纳秒

输出时间戳

1
2
1589526157
1589526157438067900

2.通过时间戳转成Time时间格式

1
2
3
t:=time.Unix(1589514825,0) //0纳秒
fmt.Println(t)
fmt.Printf("%v年%v月%v日\n",t.Year(),t.Month(),t.Day())

输出

1
2
2020-05-15 11:53:45 +0800 CST
2020年May月15

定时器

定时器使用time.Tick()方法,可以用于写循环执行的定时任务。当使用Tick()时会返回一个channel。

1
2
3
4
5
6
7

for tmp := range time.Tick(time.Second * 3){

//do something
fmt.Println(tmp) //每隔3秒打印当前时间

}

参考实例

1
2
3
4
5
6
7
8
9
10

tmp:= time.Tick(time.Second * 3)

for{

select {
case <-tmp:
fmt.Println("执行任务")
}
}

获取之后或者之前的时间

1.获取未来5小时的时间

1
2
currentTime := time.Now()
newTime := currentTime.Add(time.Hour * 5)
  1. 获取昨日时间
1
2
currentTime := time.Now()
oldTime := currentTime.AddDate(0, 0, -1) //之前就是-1

3.获取7天前的时间

1
2
currentTime := time.Now()
oldTime := currentTime.AddDate(0, 0, -7)

4.获取5天后的时间

1
2
3

currentTime := time.Now()
newTime := currentTime.AddDate(0, 0, 5) //5天后的日期就是正整数

5.两个时间相减

1
2
3
4
currentTime := time.Now()
newTime := currentTime.Add(time.Hour * 5)
t8:=newTime.Sub(currentTime)
fmt.Println(t8)

时间格式化

golang的时间格式化和其它语言格式化非常不一样,可以说独具一格。其它语言基本上为Y-m-d 或者YYYY-MM-DD这种类似。golang以是”2006 01 02 15 04 05”分别来代表
年、月、日、时、分、秒。记录口诀就是2006 1 2 3(下午的3点) 4 5

类型 表示
2006
01
02
15
04
05

样例
1.将当前时间格式成”2020/02/03 15:21:00”这种类型

1
2
3
4

currentTime := time.Now()
currentStr := currentTime.Format("2006/01/02 15:04:05")
fmt.Println(currentStr)

输出结果

1
2020/05/15 15:33:13

2.格式化精确到毫秒
在秒后面加上.000即可

1
2
3
currentTime := time.Now()
currentStr := currentTime.Format("2006/01/02 15:04:05.000")
fmt.Println(currentStr)

输出结果

1
2020/05/15 15:34:52.040

解析字符串时间

如果解析一个字符串时间呢?比如我们现在要解析字符串”2020-03-25 05:02:00”
使用Parse会根据当前时区来解析

1
2
3
4
timeStr := "2020-03-25 05:02:00"

strToTime,_ := time.Parse("2006-01-02 15:04:05",timeStr)
fmt.Println(strToTime,reflect.TypeOf(strToTime))

将字符串时间解析成指定时区时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
	//加载时区
loc,err := time.LoadLocation("America/New_York")
if err != nil{
fmt.Println(err)
return
}

timeStr := "2020-03-25 05:02:00"

strToTime,_ := time.ParseInLocation("2006-01-02 15:04:05",timeStr,loc) //指定时区变量
fmt.Println(strToTime,reflect.TypeOf(strToTime))
```

***将UTC时间"2020-05-14 02:08:23"转成当前时间***

``` go
utcTime := "2020-05-14 02:08:23"

tm,_:=time.Parse("2006-01-02 15:04:05",utcTime) //先格式化成UTC的时间

timeStamp3:=tm.Unix() //获得时间戳
tLocal:=time.Unix(timeStamp3,0) //将时间戳转成Time类型
fmt.Println(tLocal) //输出

常见用法

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
//时间类型比较,是否在Time之后
After(u Time) bool

//时间类型比较,是否在Time之前
Before(u Time) bool

//比较两个时间是否相等
Equal(u Time) bool

//判断时间是否为零值,如果sec和nsec两个属性都是0的话,则该时间类型为0
IsZero() bool

//返回年月日,三个参数
Date() (year int, month Month, day int)

//返回年份
Year() int

//返回月份.是Month类型
Month() Month

//返回多少号
Day() int

//返回星期几,是Weekday类型
Weekday() Weekday

//返回年份,和该填是在这年的第几周.
ISOWeek() (year, week int)

//返回小时,分钟,秒
Clock() (hour, min, sec int)

//返回小时
Hour() int

//返回分钟
Minute() int

//返回秒数
Second() int

//返回纳秒
Nanosecond() int

Write写入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20


func write(){
//os.O_TRUNC 会清空原来的文件
//os.O_APPEND 在原来文件中追加
fileObj,err:=os.OpenFile("xx.txt",os.O_CREATE|os.O_WRONLY|os.O_APPEND,0644)

if err !=nil{
fmt.Printf("open file failed, err:%v\n",err)
return
}

str := "成都"
fileObj.Write([]byte(str))
fileObj.WriteString("\n")
fileObj.WriteString("哈哈哈")
fileObj.WriteString("\n")

defer fileObj.Close()
}

Bufio写入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

func writeByBufio(){
fileObj,err:=os.OpenFile("xx.txt",os.O_CREATE|os.O_WRONLY|os.O_APPEND,0644)

if err !=nil{
fmt.Printf("open file failed, err:%v\n",err)
return
}

defer fileObj.Close()
writer := bufio.NewWriter(fileObj)
writer.WriteString("xxxxxx") //将内容写入到缓冲区
writer.Flush() //将缓存区内容写入磁盘


}

Ioutil写入

1
2
3
4
5
6
7
8
9
func writeByIoutil(){
str := "测试123554434"
err:=ioutil.WriteFile("./xx.txt",[]byte(str),0644)
if err != nil{

fmt.Printf("write file failed,err:%v\n",err)
return
}
}

golang文件读取3种方式

  • 1.按行读取
  • 2.读取整个内容
  • 3.分段读取

打开文件

打开文件使用os模块,使用os.Open(文件路径)

1
os.Open("./xx.txt")

参考实例

1
fileObj,err := os.Open("./test.txt") //相对目录打开文件

按行读取文件

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
package main

import (
"bufio"
"fmt"
"io"
"os"
)

func main(){
fileObj,err:=os.Open("./xx.txt")

if err !=nil{
fmt.Printf("read file failed,err:%v\n",err)
return
}

defer fileObj.Close() //defer关闭文件
s :=bufio.NewReader(fileObj)

for { //for循环逐行读取文件
reader,err := s.ReadString('\n') //指定文件每行的换行符号

fmt.Print(reader) //打印内容

if err == io.EOF{ //如果是文件结尾会抛EOF错误

break
}

}

}

读取整个文件

使用ioutil来读取整个文件内容,如果文件过大则不建议使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import (
"fmt"
"io/ioutil"
)

func main(){
content,err:=ioutil.ReadFile("./xx.txt")
if err !=nil{
fmt.Printf("read file failed, err:%v\n", err)
return
}
fmt.Print(string(content)) //将内容转成string输出
}

分块读取文件

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
package main

import (
"fmt"
"io"
"os"
)

func main(){

fileObj,err := os.Open("./xx.txt") //相对目录打开文件

if err != nil{
fmt.Printf("open file failed,err:%v\n",err)
return
}

defer fileObj.Close() //关闭文件

for {

var tmp = make([]byte,128) //按字节数读取文件内容
n,err:=fileObj.Read(tmp)

if err == io.EOF{
fmt.Print(string(tmp[:n]))
return
}

if err != nil{
fmt.Printf("read from file failed, err:%v\n",err)
}

fmt.Print(string(tmp))
}

}

panic

panic主要用于作异常处理,是一个内建的停止控制流函数。相当于其它编程语言的抛异常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

package main

import "fmt"

func getname() string{

return "name"
}

func main(){


fmt.Println("starting......!")

a :=23
if a == 23 {
panic("crash") //手动触发宕机
}
fmt.Println(getname())


}

recover

recover是内建函数,可以让进入宕机流程恢复回来,同时recover仅在defer中有效。

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
package main

import "fmt"

func getname() string{

return "name"
}

func main(){

defer func(){
err:=recover()
if err !=nil{
fmt.Println("触发宕机捕获异常:",err)
}
}() //recover只能在defer中

fmt.Println("starting......!")

a :=23
if a == 23 {
panic("crash") //手动触发宕机,后面的代码不会执行
}
fmt.Println(getname())


}

Golang 指针

指针就是一个变量,用于存储另一个变量的内存地址。这个内存地址往往是在内存中存储的另一个变量的值的起始位置。

指针特点

  • 默认值是nil,没有NULL常量
  • 操作符”&”用于获取变量地址,”*” 通过指针目标对象
  • 不支持指针运算

实例
声明一个变量x 并且设置值为1, 声明变量p 值为x的地址

1
2
3
4
5
6
7
8
9
10
11
12
13

package main

import "fmt"


func main(){
x := 1
p := &x //&获取x的地址
fmt.Println(p) //打印地址
fmt.Println(x,*p) //*p获取x所对应的值

}

以上输出结果为

1
1 1

通过指针修改变量的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

package main

import "fmt"


func main(){
x := 1
p := &x //&获取x的地址
fmt.Println(x,*p) //*p获取x所对应的值

*p = 3 //修改变量的值

fmt.Println(x,*p)

}

输出结果为

1
3 3   //*p指向x 修改*p等于修改x

指针作用函数参数

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

package main

import "fmt"


func incr(p,b *int) {
*p++
*b=*b+30
}


func main(){
x := 1
c :=2
p := &x //&获取x的地址
fmt.Println(x,*p) //*p获取x所对应的值

*p = 3 //修改变量的值

fmt.Println(x,*p)


//将x地址传递给incr函数,然后返回变量修改
incr(&x,&c)
fmt.Println(x,c)

}

输出结果为

1
2
3
1 1
3 3
4 32

new和make

在golang中,make和new都是分配内存的,但是它们之间还是有些区别的,只有理解了它们之间的不同,才能在合适的场合使用。

简单来说 new只是分配内存,不初始化内存,而make即分配又初始化内存。所谓的初始化就是给类型赋初值,比如字符为空,整型为0, 逻辑值为false等。

备注

  1. make 仅用来分配及初始化类型为 slice、map、chan 的数据。new 可分配任意类型的数据.
  2. new 分配返回的是指针,即类型 *Type。make 返回引用,即 Type.
  3. new 分配的空间被清零, make 分配空间后,会进行初始化.

new返回的是一个指针

1
2
3
name := new(string)
server := new(string)
fmt.Println(name,server) //输出0xc0000421f0 0xc000042200

golang 接口

接口可以理解为某一个方面的抽象,可以是多对一的(多个类型实现一个接口),是多态的体现。

接口是一组包含方法名、参数、返回值的未具体实现的方法的集合。

实现方式

1
2
3
4
type interfaceName interface { 
// 方法列表
GetName() string
}
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
package main

import "fmt"

type interfaceName interface {
// 方法列表
GetName() string
GetAge() int
}

type Name struct { //定义结构体
name string
age int
}

func (s Name) GetName() string { //实现两个方法
return s.name
}

func (s Name) GetAge() int {
return s.age
}

func main(){

s := Name{"roddy",28} //声明一个对象
a := s.GetName()
fmt.Println(a,s.GetAge(),s.age) //调用对象中的方法


}

空接口

空接口就是不包含任何方法的接口。所有类型都实现了空接口,并且空接口可以存任何类型的数据。

1
2
3
4
5
var allData interface{}

allData = 234

fmt.Println(allData,reflect.TypeOf(allData))

覆盖变量值

1
2
3
4
5
6
7
8
9
10
11
12
13
var allData interface{}
var allList interface{}

allData = 234

fmt.Println(allData,reflect.TypeOf(allData))

m :=123
ms := "check all"

allList = m
allList = ms //可覆盖此前的变量值
fmt.Println(allList) //此时的输出就为check all

接口零值

接口的默认值为nil

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import (
"fmt"

)



type DefaultI interface {
GetName()
}

func main(){

var mk DefaultI
fmt.Println(mk) //接口的默认值为nil

}

Ubuntu 16.4 Nginx设置访问密码

1.安装apache2-utils

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
root@rodddy:/# apt-get install apache2-utils
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
libopts25 python-meld3 python-pkg-resources
Use 'apt autoremove' to remove them.
The following additional packages will be installed:
libapr1 libaprutil1
The following NEW packages will be installed:
apache2-utils libapr1 libaprutil1
0 upgraded, 3 newly installed, 0 to remove and 199 not upgraded.
Need to get 82.1 kB/245 kB of archives.
After this operation, 810 kB of additional disk space will be used.
Do you want to continue? [Y/n] y

2.创建用户名和密码,并把用户名和密码保存到指定文件中

创建用户admin 保存的文件位置/usr/local/src/nginx/passwd

1
2
3
4
root@roddy:~# htpasswd -c /usr/local/src/nginx/passwd admin
New password:
Re-type new password:
Adding password for user admin

3.修改nginx配置文件

1
2
3
4
5
6
7
8
9
10
11
12
server {
listen 80;
server_name localhost;
.......

#新增两行
auth_basic "Please input password"; #这里是提示信息
auth_basic_user_file /usr/local/src/nginx/passwd;

location /{
.......
}

4.先检查下配置文件

1
2
3
4
root@roddy:~# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
root@roddy:~#

5.重新加载配置文件

1
root@roddy:~# systemctl  reload nginx.service

备注:

htpasswd命令选项参数说明

-c 创建一个加密文件
-n 不更新加密文件,只将htpasswd命令加密后的用户名密码显示在屏幕上
-m 默认htpassswd命令采用MD5算法对密码进行加密
-d htpassswd命令采用CRYPT算法对密码进行加密
-p htpassswd命令不对密码进行进行加密,即明文密码
-s htpassswd命令采用SHA算法对密码进行加密
-b htpassswd命令行中一并输入用户名和密码而不是根据提示输入密码
-D 删除指定的用户

创建用户

1
root@roddy:~# htpasswd -c /usr/local/src/nginx/passwd admin

添加用户(在原文件下)

1
root@roddy:~# htpasswd  -b /usr/local/src/nginx/passwd  roddy 123456

删除用户

1
root@roddy:~# htpasswd -D /usr/local/src/nginx/passwd admin

修改密码

1
root@roddy:~# htpasswd -b /usr/local/src/nginx/passwd admin 12345678

1.进入到源列表文件目录

1
root@roddy:/# cd  /etc/apt/sources.list.d/

2.编辑源列表文件

1
root@roddy:/etc/apt/sources.list.d/# vim  nginx.list

3.删除或者注释其中源即可

golang 结构体

什么是结构体?

结构体可以存不同项定义的数据类型,它是一组数据的集合。我们可以将数据按指定的格式进行保存和读取。

下面以一台服务器参数作为例子:

服务器名: ServerName
CPU: CPU
内存: Mem
硬盘: Disk
IP地址: IP

定义一个SERVER的结构体:

1
2
3
4
type 结构体名 struct {
member string // 成员及成员类型

}
1
2
3
4
5
6
7
type SERVER struct {
ServerName string
CPU int
MEM int
DISK int
IP string
}

创建结构体

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
package main

import "fmt"

type SERVER struct {
ServerName string
CPU int
MEM int
DISK int
IP string
}



func main(){
//{HOSTNAME 4 8 500 200.2.14.2} 创建一个结构体,并赋予值
fmt.Println(SERVER{"DBSERVER",4,8,500,"200.2.14.2"})


//也可以使用KEY->VALUE格式定义一个结构体
serverInfo := SERVER{ServerName:"web server",CPU:4,MEM:8,DISK:200,IP:"47.23.23.1"}

fmt.Println(serverInfo.IP)

//如果没有赋值,将使用缺省默认值
webInfo := SERVER{ServerName:"web 2server",DISK:200,IP:"47.23.23.2"}

fmt.Println(webInfo)


}

访问成员

使用方法为struct.xxxx 赋值或者访问

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
package main

import "fmt"

type SERVER struct {
ServerName string
CPU int
MEM int
DISK int
IP string
}


func main(){
//赋值
newServer.ServerName = "new server"
newServer.DISK = 500
newServer.MEM = 4
newServer.CPU = 2
newServer.IP = "2.2.3.2"

//读取

fmt.Printf("服务器名%s,磁盘:%d,内存:%d,CPU:%d,IP:%s", newServer.ServerName,
newServer.DISK, newServer.MEM,
newServer.CPU, newServer.IP,
)
}

结构体传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func GetServerInfo(server SERVER){
fmt.Printf("server ip:%s\n",server.IP) //访问结构体中的成员信息
}

func main() {


var newServer SERVER

//赋值
newServer.ServerName = "new server"
newServer.DISK = 500
newServer.MEM = 6
newServer.CPU = 2
newServer.IP = "2.2.3.2"

GetServerInfo(newServer) //将结构体传递给GetServerInfo函数

}

结构体指针

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
//结构体做为参数传递,如果要修改数据,需要用结构体指针方式
func changeServer(server *SERVER){
if server.MEM > 4{
server.MEM = 8
}
}




var newServer SERVER

//赋值
newServer.ServerName = "new server"
newServer.DISK = 500
newServer.MEM = 6
newServer.CPU = 2
newServer.IP = "2.2.3.2"

changeServer(&newServer) //结构体指针传递

//读取

fmt.Printf("服务器名%s,磁盘:%d,内存:%d,CPU:%d,IP:%s", newServer.ServerName,
newServer.DISK, newServer.MEM,
newServer.CPU, newServer.IP,
)
//结果server.MEM =8

一直在做python后端开发,之前一直会遇见django 和vue结合后的垮域问题。现特记录下解决方法

什么是跨域

解释来源链接:https://www.jianshu.com/p/3961366f9ce9

跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的。
其实我们通常所说的跨域是狭义的,是由浏览器同源策略限制的一类请求场景。

什么是同源策略?

同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指”协议+域名+端口”三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

同源策略限制以下几种行为:

  • Cookie、LocalStorage 和 IndexDB 无法读取
  • DOM 和 Js对象无法获得
  • AJAX 请求不能发送

1.安装django-cors-headers

1
pip install django-cors-headers

2.配置settings.py文件

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

//将corsheaders添加到apps中
INSTALLED_APPS = [
...
'corsheaders',
....
]



#跨域增加忽略
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True

CORS_ORIGIN_WHITELIST = (
'http://localhost:8000',
'http://127.0.0.1:8000',
)

CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
)

CORS_ALLOW_HEADERS = (
'XMLHttpRequest',
'X_FILENAME',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
'Pragma',
)


MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware', //将corshaders添加到common之上
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django_user_agents.middleware.UserAgentMiddleware',
]

3.重新启动项目即可