这一篇写结构体的基本语法、结构体解构和结构体方法语法。 结构体 与C的结构体类似。结构体是一个集合多个值成为统一类型的类型。使用struct来构造结构体。 struct STRUCT_NAME<Generic_params> { var1:type, var2:type, // ... } 如果要构造一个结构体,那么使用结构体名+大括号的语法。大括号内使用冒号分割字段名和传递的值。需要注意字段名是不允许省略的。 STRUCT_NAME { var1: param1, var2: param2 } 构造一个结构体的另一个方案是从一个已有的结构体进行复制。这可以使用.. VAR语法。在一个常规构造中列出需要单独赋值的字段,然后跟一个..加已存在的结构体。之前没有被赋值的字段会从该结构体取用。如果没有其他赋值,那这个行为就是完全复制。 如果要访问结构体内部的字段,如其他语言一样使用点语法VAR.FIELD。 这是一个实例。 struct Point { x:f32, y:f32 } fn main(){ let ...

这一部分内容可以说是很简单了,不过还是要写一篇。 分支语句 if Rust使用if——else体系作为基础分支语句。condition是判断条件表达式,不需要括号。后面的大括号无论如何都不允许省略。 if condition { // do something... } else if condition { // do something... } else { // do something else... } 可以说是很简单了。不过if还有一个别的用法,就是插入到表达式中。比如: let x = 5; let y = if x == 5 {'A'} ...

所有权系统大概是Rust语言相对于其他语言最独特的一个特性了。 这个特性让我感觉很神奇。之前见到的内存回收机制只有手动delete和GC两种,从来没有想过除了这两种方案之外的内存回收。与最近常见的越来越偏向运行时和语法糖的其他语言不同,Rust是注重内存安全和运行时速度的语言,它的绝大多数特性都是为这两个点服务的。Rust的所有权系统仅在编译期间有开销,编译完成之后这个系统不再存在,也就是说,所有权系统仅在编译时是一个“规范约束”系统,一旦编译期间代码符合规范约束,编译期就能确保运行时的约束一直生效。 引用系统和生命周期则是对所有权系统的一个补充,在安全范围内最大限度地提高代码的灵活度。 所有权 Rust语言中的变量绑定有一个特性,它拥有它所绑定的值的所有权。绑定所有权意味着一个值只有一个归属变量,并且与该变量的生命周期共存亡。 { let x = vec![1, 2, 3]; } //此处该vec的内存已经随着变量x生命周期的结束而被释放。 移动语义 单独说明所有权不能说明什么。下面说明“移动”语义。当你将一个变量所属的值绑定给另一个变量的时候,这个值的所有权就转让给了新的变量,也就是该值被“移动”了。 如果尝试访问一个被移动了的变量,就会得到一个编译错误。实际上,值的访问权与所有权是同步的,只有绑定了该值的变量可以对值进行访问。 当然,你也可以将值绑定回来,以重新取得访问权。 let x; { let y = vec![1, 2, 3]; println!("{}", y[0]); //可以访问,输出1 x = y; ...

Rust语言的函数的标准写法为: fn 函数名称(参数列表) -> 返回值 { 函数体 } 参数列表描述使用逗号分隔的、带有类型声明的参数。参数的类型声明是不允许省略的,Rust不支持全局类型推导。 如果函数没有返回值,那么箭头和返回值都可以省略不写。 Rust语言不允许省略任何必要的大括号。 Rust语言的编译与C语言不同,函数的书写不需要按照顺序。在文件中声明了的函数可以在该文件的任何位置使用。 Rust程序的入口,main函数是这个样子的: fn main() { let a = "Hello World!"; println!("{}", a); } main函数是一个典型的无参数无返回值的函数。 如果一个函数有返回值,那么它实际上还可以使用函数式语法来书写,比如: fn sum(a:i32, b:i32) -> i32 { ...

最近接触到了Rust语言,并且正在试着用它做一点作业项目。这个语言给我的感觉不同于以往的语言,让我觉得很有必要写点笔记记录一下基础语法,并且以我之前学到的语言做类比。 变量绑定 Rust的变量绑定语法相比之下更接近那些函数式语言而不是命令式。 let x = 5; 这将声明一个变量x并将其值绑定为5。let就是Rust语言的变量绑定语法。 与其他函数式语言类似,这样的写法,变量默认是不可变(immutable)的。这种不可变类似于kotlin的val或者java的final。如果想要一个可变的变量,需要使用mut关键字,这是Rust中的可变描述关键字。比如: let mut x = 5; x = 12; 不过,let语法的返回值并不是当前变量,因此let x = (let y = 1)或let x = y = 1的写法是错误的。 let语句默认进行类型推导,不过你也可以手动指定类型: let x:i32 = 12; 也可以声明一个变量但不绑定初始值,并延后进行绑定。如果这样做的话,你必须确保该变量被初始化之前不会被使用,否则会有编译错误。不指定初始值时,可以不指定类型,但前提是该变量的类型能够从下文推导出来并且编译器不会产生推导矛盾。如下: let a; a = 1; 作用域与变量隐藏 下面的写法实际上是合法的。 let x = 1; let x = 'a'; 这实际上就是下一个变量覆盖了上一个变量。...

在网上搜了一些教程之后,发现大多数的有关nginx缓存的教程都有问题,最后终于发现一篇解释了问题所在的教程,因此把正确的操作整理一遍。 为开启缓存,需要编辑nginx的配置文件。通常这个文件是/etc/nginx/sites-available/default。 配置缓存选项 在配置文件下的http大括号下添加如下配置: proxy_cache_path /path/to/cache/ levels=1:2 keys_zone=the_cache:10m max_size=10g inactive=1d; proxy_cache_key "$host$request_uri"; proxy_cache_path配置了一个缓存区域。后面的第一个参数是缓存文件的缓存路径。 * levels 表示创建的缓存级数。1:2表示创建两层缓存,最多三层。 * key_zone 缓存区的名称及大小,用:分隔。 * max_size 缓存区的最大容量。 * inactive 缓存驻留的时间。可以省略。 为代理开启缓存 在每个location的大括号下,添加如下配置: proxy_cache the_cache; proxy_cache_valid 200 302 304 24h; proxy_cache 指定该代理使用哪一个缓存区。 proxy_cache_valid 指定什么样的服务器状态码会被缓存,同时指定缓存的时间。可以设置多条来配置不同的状态码。 重启服务器 最后,执行sudo nginx -t检查,并执行sudo nginx -s reload重启即可。 ...

Nginx服务器可以进行反向代理,前一篇有关Nginx的日志就是用Nginx的反向代理功能将请求代理到Gunicorn上。而这次是要实现使用反向代理向多个本地的服务器端软件分别转发请求。 有关Nginx反向代理的官方文档:Nginx Reverse Proxy | NGINX。 下面是最常见和简单的依据URI进行匹配的转发模式。 我有两个服务器软件,一个JudgeAdmin运行在8000端口上,一个JudgeOnline运行在8008端口上,二者分别可以通过IP:8000/JudgeAdmin/和IP:8008/JudgeOnline/来访问。为了使可以通过80端口访问这两个服务器,可以这样编写nginx的配置: server { server_name online-judge; location /JudgeOnline/ { proxy_pass http://localhost:8008/JudgeOnline/; } location ...

Django REST framework中的Serializer模块是ViewSet组装部分中比较重要的一环,因此写一篇记录笔记,整理Serializer中比较常见的部分。 Serializer基础 所有的Serializer相关的类都在rest_framework.serializers包下。 Serializer的最初作用是:每种Serializer针对一类对象,可以为Serializer传入一个对象,将对象序列化为指定格式字符串;也可以传入字符串,反向序列化为对象。 下面是一个针对普通object的例子,例子取自官方文档: 类定义如下: from datetime import datetime class Comment(object): def __init__(self, email, content, created=None): self.email = email self.content = content ...

在REST API服务器中,有一些API不太好使用DRF框架快速实现,更方便的办法是直接使用Django的views函数。作为一个API服务器,url应当必须能够响应Http basic authentication,但是django的view默认是不支持的,而且似乎也没有原生的支持方案。那么可以用如下方案手动实现这个认证模式。 根据默认的规定,basic认证的认证信息经过base64加密之后储存在HTTP_AUTHORIZATION请求头中。那么我们可以手动解析信息并进行用户认证。 if 'HTTP_AUTHORIZATION' in request.META: auth = request.META['HTTP_AUTHORIZATION'].split() if len(auth) == 2 and auth[0].lower() == "basic": msg = auth[1] 这样msg就是经过base64加密的用户名:密码信息。然后进行解码: ssr = base64.b64decode(msg).split(b':') username, password ...

学校里给了两台Ubuntu服务器用来测试项目,然而在开始配置时却出现了Hash校验不符的问题。去谷歌了一下,才了解到缓存服务器这个东西。 有关缓存服务器的解释如下: 缓存指的是将需要频繁访问的网络内容存放在离用户较近、访问速度更快的系统中,以提高内容访问速度的一种技术。缓存服务器就是存放频繁访问内容的服务器。 缓存提供了比将访问对象放在Internet Web服务器上更好的方法,它将需要频繁访问的Web页面和对象保存在离用户更近的系统中,当再次访问这些对象的时候加快了速度。 虽然目的很好,但是有一部分实现很糟。他们缓存文件时,只对比文件路径,不对比域名,而且不做更新策略,导致服务器上的源更新时,缓存的文件没有跟着更新,也就造成了Hash校验不符的问题。而且由于缓存不对比域名,多数源的文件路径都是一样的,单纯的换源并不能解决问题。 在这里找到了解释以及一些解决方案(更新源时总是出现Hash校验和不符的原因以及解决方案),虽然解释清楚了原因,不过可惜写明的几种解决方法都没有解决我的问题……不过更换协议的方法还是成功了。在中科大的源Ubuntu 源使用帮助这儿找到了https协议的中科大源,比较完美地解决了问题。 换ustc的https的源 apt的源可以编辑/etc/apt/source.list文件来修改。编辑这个文件,修改内容为: deb https://mirrors.ustc.edu.cn/ubuntu/ xenial main restricted universe multiverse deb-src https://mirrors.ustc.edu.cn/ubuntu/ xenial main restricted universe multiverse deb https://mirrors.ustc.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse deb-src https://mirrors.ustc.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse deb https://mirrors.ustc.edu.cn/ubuntu/ xenial-backports main restricted ...