标签 golang 下的文章

用python生成golang支持的所有交叉编译环境脚本

虽然标题有些奇葩,但是对于我这个强迫症来说,每次golang版本更新,第一件事就是把常见的交叉编译环境给弄好,每次都写也挺麻烦,再加上随着golang版本的升级,支持的GOARCH和GOOS也不断的变多,也懒得去查wiki或者手册,就直接用下面的代码生成吧

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

__author__ = 'Chungpei Wang'
import os
import json

if __name__ == '__main__':
    env_dist = os.environ
    goroot = env_dist['GOROOT']
    gocmd = os.path.join(goroot, "bin", "go")
    result = os.popen(gocmd + " tool dist list -json")
    strresult = result.read()
    jsonresult = json.loads(strresult)
    shell_content = "#!/bin/bash" + os.linesep * 2 + "export CGO_ENABLED=0" + os.linesep * 2
    # 仅仅是因为强迫症,按照GOARCH进行排序,这样看起来整齐点
    jsonresult.sort(key=lambda k: (k.get('GOARCH', 0)))
    for data in jsonresult:
        shell_content += "export GOARCH=" + data['GOARCH'] + os.linesep
        shell_content += "export GOOS=" + data['GOOS'] + os.linesep
        shell_content += "./make.bash --no-clean" + os.linesep
        shell_content += os.linesep
    print(shell_content)

即:

1.先从系统环境变量中获取到$GOROOT
2.再执行$GOROOT/bin/go tool list list -json,获取对应版本golang所支持的所有GOARCH和GOOS
3.依次export GOARCH、GOOS,并执行make.bash(windows下应该改为make.bat)

golang初始化脚本

血的教训,windows环境中一定在golang编译的时候先停止alibaba pc safe service这个操蛋的进程!!!

@echo off

rem 环境变量定义
set BASE_PATH=%~dp0
set REAL_GOROOT=%BASE_PATH%GOROOT\go1.10.2\
set REAL_GOPATH=%BASE_PATH%GOPATH\
set DEST_GOROOT=c:\go
set DEST_GOPATH=c:\gopath

rem 打印变量
echo ========================== 环境变量 ================================
echo 当前目录为%BASE_PATH%
echo 将【%REAL_GOROOT%】链接至【%DEST_GOROOT%】
echo 将【%REAL_GOPATH%】链接至【%DEST_GOPATH%】
echo ================================================================
echo 按任意键开始
pause

echo 开始执行....

if exist %DEST_GOROOT% (
    echo 【%DEST_GOROOT%】 已存在,即将删除
    rd /s /Q %DEST_GOROOT%
) else (
    echo 【%DEST_GOROOT%】 不存在
)
mklink /J "%DEST_GOROOT%" "%REAL_GOROOT%"
::如果有的话,先删除GOROOT
wmic ENVIRONMENT where "name='GOROOT'" delete
::创建GOROOT
::wmic ENVIRONMENT create name="GOROOT",username="<system>",VariableValue="%DEST_GOROOT%"
wmic ENVIRONMENT create name="GOROOT",username="%username%",VariableValue="%DEST_GOROOT%"


if exist %DEST_GOPATH% (
    echo 【%DEST_GOPATH%】 已存在,即将删除
    rd /s /Q %DEST_GOPATH%
) else (
    echo 【%DEST_GOPATH%】 不存在
)
mklink /J "%DEST_GOPATH%" "%REAL_GOPATH%"
::如果有的话,先删除GOPATH
wmic ENVIRONMENT where "name='GOPATH'" delete
::创建GOPATH
::wmic ENVIRONMENT create name="GOPATH",username="<system>",VariableValue="%DEST_GOPATH%"
wmic ENVIRONMENT create name="GOPATH",username="%username%",VariableValue="%DEST_GOPATH%"

echo 执行完成,请手动在环境变量PATH中添加【%DEST_GOROOT%\bin】
echo 按任意键结束
pause

解决golang ssh包报错 ssh: must specify HostKeyCallback

client, err := ssh.Dial("tcp", "192.168.1.71:22", &ssh.ClientConfig{
        User: "kevin",
        Auth: []ssh.AuthMethod{
            ssh.Password("123456"),
        },
        //需要验证服务端,不做验证返回nil就可以,点击HostKeyCallback看源码就知道了
        HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
            return nil
        },
    })
    fmt.Println(err)
    fmt.Println(client)

国内安装golang.org下的包(如net、crypto等)

因为某些不可描述的原因,在国内环境下使用

go get golang.org/x/net

是无法下载成功的,比较幸运的是,golang目前所有源码已经托管在github.com上,仔细观察下载路径,其实可以采用变通的方式解决这个问题

golang.org/x/net 其实对应了 github.com/golang/net,即golang上的x/??? 直接对应了github上的 ???
我们可以先

go get github.com/golang/net

将对应的包下载到$GOPATH中,再进入$GOPATH/src路径下

mv github.com/golang/net golang.org/x/net

这里需要注意根据操作系统的不同,可能需要预先根据url创建好各层文件夹

另一侧解决办法,访问以下网站手动下载包
https://gopm.io/download

解决Golang爬虫出现Connection reset by peer或EOF的问题

【问题】
一个http Client程序代码如下:

// create a request
req, err := http.NewRequest(method, url, body)
if err != nil {
    return nil, err
}

// send JSON to firebase
resp, err := http.DefaultClient.Do(req)
if err != nil {
    return nil, err
}

if resp.StatusCode != http.StatusOK {
    return nil, fmt.Errorf("Bad HTTP Response: %v", resp.Status)
}

defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
    return nil, err
}

多次发给服务器后,几乎每次都会出现下面的错误:

ERROR 10108 socket.cpp:985 0x7fffe81426e0 recvmsg(62, 1): (104, "Connection reset by peer")
WARN 10108 server.cpp:467 0x7fffe80abd60-2 Unexpected SocketException

【原因】

在解决问题之前需要了解关于go是如何实现connection的一些背景小知识:有两个协程,一个用于读,一个用于写(就是readLoop和writeLoop)。在大多数情况下,readLoop会检测socket是否关闭,并适时关闭connection。如果一个新请求在readLoop检测到关闭之前就到来了,那么就会产生EOF错误并中断执行,而不是去关闭前一个请求。这里也是如此,我执行时建立一个新的连接,这段程序执行完成后退出,再次打开执行时服务器并不知道我已经关闭了连接,所以提示连接被重置;如果我不退出程序而使用for循环多次发送时,旧连接未关闭,新连接却到来,会报EOF。

【解决】
对 req 增加属性设置:

req.Close = true

它会阻止连接被重用,可以有效的防止这个问题,也就是Http的短连接