golang客户端取消http请求
Tag golang, cancelable, http, on by view 1321

首先,创建带有Cancel Context的http请求

var cx context.Context
cx, req.cancel = context.WithCancel(context.Background())

if req.httpreq, err = http.NewRequest(req.method, req.url, reqbody); err != nil {
    return
}
req.httpreq = req.httpreq.WithContext(cx)
req.httpreq.Header = req.Headers
req.httpreq.ContentLength = reqbodyLength

然后,需要停止请求的时候调用req.cancel()方法

if req.cancel != nil {
    req.cancel()
    fmt.Println("running cancel...")
}

return nil

这样才能够客户端强行主动取消正在进行的http连接。就是这么简单


关于阿里云ESC上go语言项目编译6l: running gcc failed: Cannot allocate memory
Tag golang,编译,内存不够,swap, on by view 3072

前段时间将自己的阿里云服务器上的系统由centos 6.5换为了ubuntu 14,其他的硬件配置都没有发生改变,将服务器上的数据恢复并且重新安装了golang的编译环境后,发现使用go build编译稍微大一点的golang项目就会报错:

/usr/local/go/pkg/tool/linux_amd64/6l: running gcc failed: Cannot allocate memory

一直想不通为啥换了个系统就会报这个错,字面意思是gcc分配内存失败,应该是内存不够用,机器配置是1G内存,free -m 发现尚有400M的内存未使用,难道剩余400M的内存还不够go build命令编译代码使用?好吧,既然如此我就给它释放内存,kill掉众多的进程之后再进行go build编译,发现又可以编译了。之后发现偶尔能编译偶尔又不能编译,看样子确实是内存不够,可是为啥之前的centos系统上没有出现这种状况呢,一直不相信简单的“内存不够”就可以解释这一问题,因为之前的centos系统上是正常的,我甚至觉得可能是gcc版本的问题,猜测只有较高版本的gcc才会报这个错误。后来也曾在“golang天朝”论坛上发过帖子,并表达自己的猜测,认为不是内存不够这么简单,结果被别人鄙视不看英文……

不想花钱升级机器硬件,难道我只有装回centos?今天执行free -m偶然间注意到了swap的数值貌似一直是空的,我思考若是我添加swap交换空间是否能解决这一问题呢,毕竟swap其实就是用硬盘空间虚拟出的内存,一个内存的缓冲区。于是就给它加了个1G的文件作为swap,居然直接就可以用go build,再也不用担心gcc对我说Cannot allocate memory了。简单的记录一下添加文件作为swap的步骤:

  • 创建1个1GB的file

sudo dd if=/dev/zero of=/mnt/1GB.swap bs=1M count=1024
  • 格式化为Swap file

sudo mkswap /mnt/1GB.swap
  • 把swap file加入到系统中

sudo swapon /mnt/1GB.swap
  • 将swap永久添加
    在/ect/fstab中加入新的Swap分区

sudo gedit /etc/fstab
  • 在最后加入下列内容

/mnt/1GB.swap none swap sw 0 0

最后,free -m 命令可以看到swap的数据如下

             total       used       free     shared    buffers     cached
Mem:           992        903         88          0         57        188
-/+ buffers/cache:        656        335
Swap:         1023          0       1023

1G的内存交换区文件已经创建。


Go语言新手应该知道的几点
Tag golang,初学者,包导入,变量命名, on by view 4491

1. 变量与函数命名

在go语言中变量与函数的命名是有着特殊的限制的,比如,一个函数functionname与函数FunctionName是有着不同的特点的。函数名第一个字母大写表示此函数可以被其他文件中的代码所调用,而函数名第一个字母小写的函数却只能在当前文件中被调用。初学者往往会发现自己正确的导入了包,但是却无法调用包里面的函数,这时候请看一下自己定义的函数名的首字母的大小写情况。因此,建议Go语言变量命名一律使用骆驼命名法(FunctionName/functionName),而不是蛇形命名法(function_name)。

2. 包导入import

(1) 相对路径

import "./model" //当前文件同一目录的model目录,但是不建议这种方式来import

(2) 绝对路径

import "shorturl/model" //加载gopath/src/shorturl/model模块

(3) 点操作

import( . "fmt" ) 
这个点操作的含义就是这个包导入之后在你调用这个包的函数时,你可以省略前缀的包名,也就是前面你调用的fmt.Println("hello world")可以省略的写成Println("hello world")

(4) 别名操作
别名操作顾名思义我们可以把包命名成另一个我们用起来容易记忆的名字

import( f "fmt" ) //别名操作的话调用包函数时前缀变成了我们的前缀,即f.Println("hello world")

(5) _操作

import ( "database/sql" 
         _ "github.com/ziutek/mymysql/godrv" 
        )
_操作其实是引入该包,而不直接使用包里面的函数,而是调用了该包里面的init函数