漫游Go语言(八)之sync.Mutex
sync.Mutex
Go为mutual exclusion提供sync.Mutex库的两个方法
我们可以将一块代码用Lock和Unlock包围以实现互斥运行,还可以用defer
关键字来确保mutex
会被释放。
练习:网页爬虫
在练习将使用Go并发特性来实现并行爬虫。修改Crawl
方法并行但不重复地获取URL。
提示,可用一个Map来保存已获取的URL,但Map本身并不是线程安全的。
Go为mutual exclusion提供sync.Mutex库的两个方法
我们可以将一块代码用Lock和Unlock包围以实现互斥运行,还可以用defer
关键字来确保mutex
会被释放。
在练习将使用Go并发特性来实现并行爬虫。修改Crawl
方法并行但不重复地获取URL。
提示,可用一个Map来保存已获取的URL,但Map本身并不是线程安全的。
goroutine
是由go runtime
所管理的轻量级线程。go f(x,y,z)
开启一个运行f(x,y,z)
的新goroutine。f
,x
,y
,z
值的计算发生在当前goroutine
,但f的执行则在新的goroutine
中。
goroutine
运行在同一地址空间中,所以共享内在的存取必须同步,sync
包提供一些有用的基本工具,但一般你用不到它们,因为还有其它的工具。
channel
是一种有类型的管道,使用<-
操作符就可以通过它发送和接收数值。
参数按箭头的方向流动。和map
及slice
一样,channel
也需要先定义再使用。
样例代码将slice
中数累加,将工作分布在两个goroutine
中,当二者完成时,得到最终结果。
Go
使用error
类型的值来表示错误,这是一个内建的类似Stringer
的接口。
类似Stringer
,fmt
包也会寻找error
接口来打印值。
函数经常以error
作为返回类型,调用函数的代码应该通过检测error
是否为nil
并处理处理。一般来说error == nil
说明无错误,而非nil则代表failure.
实现一个开方函数,除返回结果外,还返回error
,当被操作数是负数是返回一个非nil
的error
,其Error()
方法返回“cannot Sqrt negative number: -2”信息。
创建一个MyFloat
的类type MyFloat float64
,然后实现func (mf MyFloat ) Error() string
使之成为一个error
。
这是我的答案
Go没有类,但是能为类型定义方法method
。所谓方法就是一个具有特殊receiver
参数的函数,receiver
在自己的参数列表中,位于func
关键字与函数名之间。method
只是一个有着receiver
的特殊函数。
你也可以为非struct
的数据类型定义方法,如type MyFloat float64
,但方法和类型必须在同一包下。
如果需要更改该类型变量的值,那么就要用到pointer receiver
。如果使用值参数,那么就是值传递,其它普通函数也是一样的。
method
不同于一般function
之处在于其receiver
为pointer
时,即可以接受pointer
也可以接受value
的变量的调用,其效果都等同于传入pointer
。同理当method
的receiver
为value
时,不管传入pointer
还是value
,效果都是值传递。
Map就是Key-value对。map必须make
后才能使用,nil
的map
是无法赋值的。
map literals
和struct literals
是类似的,不过key
是必须的。
|
|
如果顶层类型只是一个类型名,可以将它从literal
元素们中省略。
Go是有指针的,*T
定义一个指向T类型的指针,其缺省值为nil
.
类似地,&
操作符可以取操作数的地址。
而*
操作符也可以取指针指向的值
但与C
不同的是,Go没有指针运算。
struct
是一组域
的集合
struct的域可以通过.
来存取。
Go只是一种循环控制语句for
,由分号;
分开的三部分作为与C同,其初始化部分通常用:=
形式的短声明,其作用域只在循环内。
注意与C
,java
等不同的是,条件部分无括号,而循环体的{}
则不可省略。初始化与post循环体语句可省略,;
也可以省略,如果什么都不带,则代表死循环。
死循环
这只是我follow tour.golang.org时的笔记(翻译)。
Go程序都由包组成,从main
包开始执行。
以上程序导入了match
和math/rand
两个包,按约定包名与路径最后一部分相同,比如math/rand
目录下的文件都以package rand的声明开头。
可以将多个包用括号一起导入,如
当然也可以用多个语句分别导入,但推荐以上方式。
本文介绍如何使用Flask微框架在Ubuntu 15.10上搭建一个WEB应用,并使用guniconr Server来启动应用和设置Nginx作为前端反向代理。
gunicorn是一个运行于unix环境的遵循python WSGI规范的WEB Server。WSGI(web server gateway interfaces)是一种python中定义WEB应用/框架 与 WEB服务器/应用服务器之间通信规范的接口标准,旨在简化和规范上述部件间的通信,并使各部分易于替换。它定义了一组可用于其它协议之上的接口。
因此作为一种WSGI实现的gunicorn可以将HTTP请求转换为WSGI定义的python标准请求,可被同样遵循了WSGI规范的应用如django,flask接收处理,处理后的响应也同样可被逆向转换为http response并回到客户端。
nginx在此场景中则作为一个http request代理,将不uri或类型的请求发送至不同的web server处理,比如静态图片可由自己处理,而动态的数据库查询可交给flask应用来完成。
如果要使用systemd来实现开机自启动,一般将后缀为.service
的unit configuration file
放置在/etc/systemd/system/
下。
如果只是简单地运行一个shell脚本:
如果还需要关闭的话,则需要加一行ExecStop,并相应修改:
(yourscript脚本接受两种参数并执行不同操作)
当然也可以用简单地shell命令来代替unit configuration file规则
.service文件编写好之后,可以使用
来启动服务。
如果.service文件有修改 ,可以需要使用systemctl daemon-reload
命令重新加载。
更多的内置关键字和用法,可以参考https://wiki.ubuntu.com/SystemdForUpstartUsers