这里使用的是官方的包管理工具dep  https://github.com/golang/dep

背景 gitlab 10.5.6,gitlab_ci,golang 1.10.1,dep v0.4.1

1:安装,直接在github下载二进制文件,放入系统的path目录即可

2:遇到的问题

2.1 go get gitlab项目失败

git config –global url.”git@git.ciphp.com:”.insteadOf “https://git.ciphp.com/” 使用ssh的方式替代https的模式,这样可以用证书拉项目

2.2 dep init 不能在软链接目录执行

暂时无解,请到gopath非软链接目录执行

2.3 dep ensure is not within a known GOPATH/src

如果登录到gitlab ci机器,能手工执行成功,修改.gitalb-ci.yml执行脚本的pwd环境变量

php偏移量16个0

openssl_encrypt($xml,’AES-128-CBC’,$key, false, hex2bin(‘00000000000000000000000000000000’));

//java代码是服务提供方写的,目前知道这样写的对方能解出来,不懂java就不写代码了.

golang

package main

import (
“bytes”
“crypto/aes”
“crypto/cipher”
“encoding/base64”
“fmt”
“io”
“log”
“os”
)

var iv = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
//必须这样写,如果写成[]byte(“16个0”)会丢失前面16个字节

func main() {
TestCBCAES()
}

func TestCBCAES() {
key := []byte(“IHqnFXMNhpzYNLOU”)
data := “xmlssssss”
result, err := AesEncrypt([]byte(data), key)
if err != nil {
panic(err)
}
origData, err := AesDecrypt(result, key)
if err != nil {
panic(err)
}
fmt.Println(string(origData))
}

func AesEncrypt(origData, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
origData = PKCS5Padding(origData, blockSize)
blockMode := cipher.NewCBCEncrypter(block, iv)
crypted := make([]byte, len(origData))
blockMode.CryptBlocks(crypted, origData)
return crypted, nil
}

func AesDecrypt(crypted, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
//blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, iv)
origData := make([]byte, len(crypted))
// origData := crypted
blockMode.CryptBlocks(origData, crypted)
origData = PKCS5UnPadding(origData)
return origData, nil
}

func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize – len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext…)
}

func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
// remove the last byte
unpadding := int(origData[length-1])
return origData[:(length – unpadding)]

}

golang代码参考,修改了偏移量的方式,可能跟服务端实现的方式有关系

如何讓 AES 在 Golang 與 Android(Java) 得到一致的加解密結果

GO项目跑整个项目的覆盖率

gitlab-ci.sh 内容如下

set -e echo “mode: atomic” > coverage.txt

for d in $(go list ./… | grep -v vendor | grep -v doc); do
go test -race -coverprofile=profile.out $d
if [ -f profile.out ]; then
cat profile.out | grep -v statements | grep -v atomic >> coverage.txt
rm profile.out
fi done

go tool cover -func=coverage.txt

go 1.10 之后建议使用如下代码

set -e
go test -race -coverprofile=coverage.txt $(go list ./… | grep -v “vendor” | grep -v “doc”)
go tool cover -func=coverage.txt

gitlab页面设置

导航到页面settings/ci_cd 展开节点:General pipelines settings–>Test coverage parsing

输入 total:\s+\(statements\)\s+(\d+.\d+)%

刚开始使用gitlab的单元测试覆盖率,测试的代码是golang的,经过摸索如下

total:\s+\(statements\)\s+(\d+.\d+)%

.gitlab-ci.yml 配置文件如下

script:
- go test -coverprofile=coverage.out && go tool cover -func=coverage.out

就是从输出的内容里面用正则匹配,能成功就OK了

服务端

processor := enameepp.NewEppContactProcessor(&EppStruct{})
domainProcessor := enameepp.NewEppDomainProcessor(&EppStructDomain{})
TMultiplexedProcessor := thrift.NewTMultiplexedProcessor()
TMultiplexedProcessor.RegisterProcessor("contact", processor)
TMultiplexedProcessor.RegisterProcessor("domain", domainProcessor)

server := thrift.NewTSimpleServer4(TMultiplexedProcessor, transport, transportFactory, protocolFactory)

fmt.Println("Starting the simple server... on ", addr)
return server.Serve()

客户端

var transport thrift.TTransport
var err error
transport, err = thrift.NewTSocket(addr)
if err != nil {
	fmt.Println("Error opening socket:", err)
	return err
}
transport = transportFactory.GetTransport(transport)
defer transport.Close()
if err := transport.Open(); err != nil {
	return err
}

protocol := thrift.NewTBinaryProtocolTransport(transport)
mp := thrift.NewTMultiplexedProtocol(protocol, "domain")

//client := enameepp.NewEppContactClientProtocol(transport, protocol, mp)
client := enameepp.NewEppDomainClientProtocol(transport, protocol, mp)
return handleClient2(client)

原始代码

for {
	select {
	case poll := <-connPool:
		print("pool")
	case <-time.After(20 * time.Second):
		break //希望在这里退出循环
	}
}

结果是一直在循环,搜索了下发现这样写是不对的,改进代码

OK:
for {
	select {
	case poll := <-connPool:
		print("pool")
	case <-time.After(20 * time.Second):
		break OK //这样就可以退出了
	}
}

使用SSH包写了一个SCP文件到远程服务器的东东

func sendFile(client *ssh.Client, src string, dest string) error {
    session, err := client.NewSession()
    if err != nil {
        return err
    }
    defer session.Close()
    go func() error {
        w, errs := session.StdinPipe()
        if errs != nil {
            return errs
        }
        defer w.Close()
        fileSrc, srcErr := os.Open(src)
        if srcErr != nil {
            return srcErr
        }
        srcStat, fileErr := fileSrc.Stat()
        if fileErr != nil {
            return fileErr
        }
        fmt.Fprintln(w, &quot;C0644&quot;, srcStat.Size(), filepath.Base(dest))
        io.Copy(w, fileSrc)
        fmt.Fprint(w, &quot;x00&quot;) // 传输以x00结束
        return nil
    }()
    if err := session.Run(&quot;/usr/bin/scp -qrt &quot; + filepath.Dir(dest)); err != nil {
        return err
    }
    return nil
}

在服务器上执行一个PY脚本

func execCmd(client *ssh.Client, cmd string) (error, string) {
    sessions, err := client.NewSession()
    if err != nil {
        return err, &quot;&quot;
    }
    defer sessions.Close()
    str, errc := sessions.CombinedOutput(cmd)
    return errc, string(str)
}

结果

SCP文件是正常的,在执行PY脚本的时候代码也全部执行了,不过输出的结果不一致
和在服务器上直接执行python xxx.py par1 par2 不一样
xxx.py

os.system(‘tar zxvf xxx.tar.gz’)//这个会显示解压文件的路径
ptint(“start”)
os.system(cp xxx.class)
print(“stelp 2”)
os.system(‘tar zcvf xxx.tar.gz ./’)//这个会显示路径

GO得到的结果

显示tar zxvf 的结果
显示tar zcvf 的结果
print(start)
print(step 2)

没闹明白为啥这样的 是不是和PY调用系统命令有关系.

编译libgit2

$ mkdir build &amp;&amp; cd build
$ cmake ..
$ cmake --build .

给的是这个,不过编译了会找不到,根据后面的提示

$ cmake .. -DCMAKE_INSTALL_PREFIX=/install/prefix
$ cmake --build . --target install
安装到/usr/local目录下

编译git2go

git submodule update --init # get libgit2 就开始下载了
make install

string 转JSON

mapJson := map[string]string{“ip”: localIp, “log”: str}
mapJsonStr, err := json.Marshal(mapJson)

json to map/struct

content := `{“ip”:”192.168.200.53″,”log”:”fsadfasdfaf”}`
var nl map[string]interface{}
errs := json.Unmarshal([]byte(content), &amp;amp;amp;amp;nl)
if errs != nil {
fmt.Println(errs)
}
fmt.Println(nl[“ip”])

数组 和 字符串转换

int to str :strconv.Itoa(count)
str to int :strconv.Atoi(count)

时间转换

str :=”04/Sep/2014:16:18:08″
t, err := time.Parse(“02/Jan/2006:15:04:05”, str)
if err != nil {
fmt.Println(err)
}
fmt.Println(t)
fmt.Println(t.Format(“2006-01-02 15:04:05”))//得到年-月-日 时:分:秒 格式

这文章不错https://gobyexample.com/json

起因:编译好的GOLANG 可执行文件在内网服务器上跑,突然一天日志显示连接对方EPP服务器的时候提示handshake_failure

分析:想了下这应该是EPP服务器的证书有变化(不过沟通后对方说没有变化,只能自己折腾了)

直接使用OPENSSL 尝试连接 发现是正常的,能够看到EPP的greeting 说明对方的也是正常的,猜想应该是对方修改了什么但是GO不支持

用NODEJS 写了一个测试文件 发现是连接正常 所以应该是GOLANG 不支持的原因

继续阅读