cover

Rust-所有权

所有权系统和引用在Rust中是至关重要的,它的设计使得rust的GC机制与众不同,也让rust获得了性能上的回报。 所有权 所有权:一个数值只能被一个变量所拥有,即该变量唯一拥有该数值,若变量离开了其作用域,数值也会被释放掉。 如果将一个变量赋值给另一个变量,则意味着对应的值的所有权会被移交出去,那么原先的变量将不再拥有值的所有权,这也是为什么在rust中,变量的赋值也叫变量的绑定。 // 例子 fn main(){ let s1 = String::from("Hello"); let s2 = s1; // 所有权移交 -> 即move println!("{}", s1); // 报错 } 可以看到,上述例子的s1将所有权移交给s2后,自己便不再拥有对字符串Hello的控制。 从内存的视角观察 还是上述例子,在内存里表示出来,如下图所示。 可以看出,再进行变量绑定时,s2实际上是s1的浅拷贝结果,但唯一不同的是指针的移交操作,即指针不是单纯的拷贝,而是从s1上“移交”给了s2,这也是一个move的过程。 如果不想让s1的所有权移交出去,则可以调用String的clone方法来实现深拷贝 ,在堆内存上再开辟一个空间,这样两个变量都有对应的值,这样就不会发生变量无法使用的情况了。 let s1 = String::from("hello"); let s2 = s1.clone(); // 直接重新开辟一个空间,尽量少用,会影响rust性能 println!("s1 = {}, s2 = {}", s1, s2); 需要注意的是,这并不能说明存储在堆内存中的数据只能有一个引用(即指针),这里只强调了move这个操作,即所有权的移交过程,而没有说明堆数据只能有一个引用。 Copy类型 之所以提到copy类型是因为它与上述的String类型有所不同,具有Copy属性的数据类型的数据都是直接存储于栈内存中的,即具有copy特征的数据在进行赋值时,旧变量依然可以使用。 fn main(){ let a = 1; let b = a; // 将 a 赋值给 b } 当赋值时,进行了浅拷贝操作,由于简单类型直接在栈上进行浅拷贝,开销小,两个1时存储在不同的栈内存空间里,所以两个变量都有与之对应的数值,所以不会像刚才的String类型一样,发生s1不可使用的情况。...

October 26, 2022 · 1 min · 82 words · Runtus

再拾docker

记录docker的基本概念和用法,系统的再认识一次docker docker是什么 Docker是对Linux容器的一种封装,并提供简单易用的接口,同时它也是目前最流行的Linux容器解决方案。 在docker出现之前,环境移植一直是非常麻烦的事情,当我们需要把项目从一台机器迁移到另一台机器时,不仅仅是迁移源代码,更重要的是要保证环境的一致性,而一次次环境的搭建则显得冗余且效率极低,所以在思考有没有一种方式能够把环境一起进行迁移。 虚拟机的出现在一定程度上解决了这个问题,但接踵而至的问题是: 虚拟机占用资源多,它本质就是一台完整的操作系统, 冗余步骤多,由于是完整的操作系统,一些系统级别的操作步骤不可避免。 启动慢。 所以Linux发展出了另一种虚拟化技术:Linux容器。而docker则是Linux容器的一种解决方案(也是最流行的) 可以简单的将docker理解为一种非常轻量级的虚拟机。 docker镜像(image文件) docker把应用程序及其依赖打包在image文件里,通过image文件,就会生成容器(后续会提到),即镜像文件其实就是容器的模版,而容器则是镜像文件的实例(可以一一对应类与对象) image文件是二进制文件。在实际开发中,我们会在别人写好的image文件上加一些自定义设置从而形成我们需要的image文件,而不是自己从零开发一个image文件(当然,有需求另说)。 # 有关image命令 docker image ls # 列出docker镜像 docker image rm [imageName] # 删除某镜像文件 容器文件 由image生成的容器实例,本身也是一个文件,称为容器文件。同时,当关闭容器时不会删除容器文件,只是让容器停止运行而已。 docker container ls # 本机正在运行的容器 docker container ls --all # 本机所有容器 每个容器都有一个唯一ID,如果需要终结容器的运行,需要使用kill命令docker container kill。 如需要删除容器文件,需要使用rm命令。 docker container rm [containerID]

January 29, 2022 · 1 min · 47 words · Runtus

go-learning-1

Golang学习记录 关于swtich Golang中的switch的每个case自带break关键字,即不用手动去设置break关键字。 import ( "fmt" ) func main(){ variables := 12 switch variables { case 24: fmt.Println('24') case 12: fmt.Println('12') case 36: fmt.Println('36') default: fmt.Println('114514') } } // 12 如果在其他语言中这样编写switch代码块,36和default代码块中的输出也会执行。 fallthrough关键字 当然,golang也提供了能够无视掉默认break的关键字,即fallthrough,在指定的case最后一行加上fallthrough,则对应的case代码块将会忽视掉默认的break操作。 // 接上 func main(){ variables := 12 switch variables { case 24: fmt.Println('24') case 12: fmt.Println('12') fallthrough case 36: fmt.Println('36') default: fmt.Println('114514') } } // 12 // 36 关于数组 在golang中的数组和c一样,一旦定义了大小就不可更改,且声明方式有多种,如下: // var variable_name [SIZE] variable_type func main(){ var balance = [3]float32{100, 2....

January 28, 2022 · 2 min · 384 words · Runtus

0120-浏览器事件

Javascript和HTML的交互都是通过事件来实现的,而事件的产生与执行则是遵循着传统软件工程领域中的观察者模式,其能够做到页面行为和页面展示的解耦合。 本节内容会从事件流谈起,然后逐一介绍几种注册事件的方式以及他们其中的一些细节,最后还会提到关于**事件委托(代理)**的概念。 事件流 事件流描述了页面接受事件的顺序。因为一个事件的触发可能会影响好几处地方,这很容易理解,比如在页面上嵌套着写了几个div元素,同时在最里层的div元素上进行事件触发,那这不仅仅是最内层的div对事件进行响应,任意一层的嵌套的div都会对事件进行相应处理。(其实通过上述的观察者模式也可以推断出其合理性,因为一个对象可以由多个观察者进行观察) 所以多个监听事件的元素响应顺序需要进行统一,因为一些历史原因,事件的响应顺序有两种模式:冒泡和捕获。 事件冒泡 顾名思义,事件的冒泡就如水底下的气泡一下,从内到外,同理,事件冒泡规定的事件流顺序也是从内而外,事件会从最深层的节点开始触发,然后向外传播到document(文档)。 代码如下所示。 <html> <body> <div id="ddd"> click me </div> </body> </html> 此时我如果对id=ddd的div元素进行click事件触发,那么该事件会以如下顺序发生: div body html document 现代的浏览器的事件会一直冒泡到window对象。 事件捕获 事件捕获则和事件冒泡相反,事件的响应顺序是从外到内的,还是以上一个例子为例,那么对应click事件讲会以如下顺序发生: document html body div DOM事件流 DOM2 Events规范里规定里事件流为分三个部分:事件捕获,到达目标和事件冒泡。 需要注意的是,div元素(即直接触发元素)是不会响应捕获事件的,因为通常认为直接触发事件是冒泡阶段发生的,所以它也是冒泡阶段第一个发生的事件。 但现在大多数支持DOM事件流的浏览器都实现了一个小小的拓展,即在捕获阶段在事件目标上触发事件。最终结果表现为有两个机会来处理事件。 事件处理程序 事件意味着用户或浏览器执行的某种动作,而为响应事件而调用的函数被称为事件处理程序(事件监听器)。 HTML事件处理程序 HTML事件处理程序是以HTML属性的形式来进行指定的。该属性的值必须是能够执行的javascript代码。 比如下面这个例子,就是按钮在被点击时执行一段代码。 <button onclick="console.log('click')"> click me </button> 当然也可以以函数的形式来进行响应事件定义。 <script> function click(event){ console.log('click') } </script> <button onclick="click(event)"> click me </button> 可以看到,除了把函数单独拎出来以外,还多了一个event对象,这个是一个特殊的局部变量,它定义了事件触发的一些属性以及被触发元素的一些属性。 除此之外,HTML事件处理程序中的this就是DOM元素本身,所以可以直接使用this对象去获取对应元素上的属性。 <input type="button" value="Click Me" onclick="console.log(this.value)"> 这里还有个比较有趣的地方,获取元素属性时可以直接省略掉this,直接使用value,即下面写法也能达到同样的效果。 <input type="button" value="Click Me" onclick="console.log(value)"> 因为这个包装函数在创建时其作用域链被with操作符给延长了,所以document和元素自身的成员都可以被当成局部变量来使用。 function() { with(document) { with(this) { // 属性值 } } } 但最好不要这样做,因为不仅仅会显得很诡异,而且在后期调试时也会造成误解。 HTML事件处理程序一个比较大的问题是:它把HTML和Javascript在代码上进行了强耦合(在逻辑上依然是分开的),如果我们需要更改响应程序,那么两处都需要进行修改。...

January 20, 2022 · 2 min · 260 words · Runtus

DOM扩展

虽然原生DOM API已经能做许多事情了,但是仍然不断有标准或专有的扩展出现,以支持更多的功能,由于各个浏览器对DOM扩展的支持是专有的,为了统一这些专有的DOM API,W3C开始着手将这些专有扩展转变为标准规范。 Selectors API Selectors APIs 是浏览器原生支持的CSS查询API,由于是原生支持,解析和遍历DOM树可以通过底层编译语言实现,相比其他Javascript库(比如jQuery),性能有数量级的提升。 Selectors API Level 1 主要是两个API:querySelector() 和 querySelectorAll() querySelector() 该方法接受CSS选择符参数,返回匹配到的第一个后代元素,如果没有匹配元素则返回null。 // 匹配 class 为 list 的第一个DOM元素 document.querySelector('.list') // 匹配 id 为 myDiv 的第一个DOM元素 document.querySelector('#myDiv') // 匹配 class=header DOM元素子元素中 id为someDiv的元素 const header = querySelector('.header'); header.querySelector('#someDiv') 如果直接在document上使用querySelector方法,会从文档元素开始搜索(前两个例子);在Element上使用querySelector方法,则只会在该元素的后代中查询(第三个例子)。 querySelectorAll() 该方法和querySelector类似,接受CSS选择符参数,只不过它会返回匹配的所有节点。即返回的是一个NodeList的静态实例。 ⚠️注意:无论是querySelector还是querySelectorAll返回的都是DOM元素的静态快照,即和之前提到的getElementById获取的动态实例不同,更改静态快照是不会影响DOM元素在页面上的渲染。 matches() matches方法接受一个css选择符参数,用于判断是否存在对应css选择符的DOM元素,如果存在返回true,否则返回false。 if(document.body.matches("body.header")){ // true } CSS类扩展 HTML5增加了一些特性以方便使用CSS类。 getElementsByClassName() 该方法接受一个参数,包含一个或多个类名的字符串,返回类名中包含对应类的元素的NodeList。 // 返回 class 包含 username 和 current 的类 document.getElementsByClassName('username current') classList属性 classList属性提供了快速操作DOM元素类名的方法,如果是之前,对一个含有多个class的DOM元素进行类名操作会很麻烦,基本操作都是把其类字符串解析成数组,然后一个一个进行匹配操作,最后再合并为一个新的类字符串重新赋值回去。 // 要删除"user"类 let targetClass = "user"; // 把类名拆成数组 let classNames = div....

December 26, 2021 · 1 min · 114 words · Runtus