很多公司都是使用go语言来开发程序,但是开发中以及最终交付的代码需要满足以下条件:
build.shbuild.sh/etc/profilegitgitgolandgolandgolandmain
的
国外网址可能不行,直接从以下网址下载即可
https://www.gomirrors.org
下载的时候需要注意以下几点:
apt-getbrewgolandgolangGOMODULE
Macbrew
# 查看go的路径
fh@Feihu-3 go % which go
/usr/local/bin/go
# 实际上,这是一个软连接
fh@Feihu-3 go % ls -l /usr/local/bin/go
lrwxr-xr-x 1 fh admin 26 8 22 16:01 /usr/local/bin/go -> ../Cellar/go/1.16.6/bin/go
fh@Feihu-3 go %
# 这些信息是没有修改过的
# 如果修改过的环境变量,存放的路径是GOENV中
# 修改命令,eg:
# go env -w GO111MODULE=on
fh@Feihu-3 go % go env
GO111MODULE="" # 模块管理,注意此项
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/fh/Library/Caches/go-build"
GOENV="/Users/fh/Library/Application Support/go/env" # 当前变更的记录环境变量路径
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/fh/go/pkg/mod" # 下载的第三方包的路径
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/fh/go" # GOPATH,视情况而定
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct" # 从某个域名去下载第三方包,一定修改
GOROOT="/usr/local/Cellar/go/1.16.6/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.16.6/libexec/pkg/tool/darwin_amd64"
GOVCS=""
GOVERSION="go1.16.6"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/8m/dwtpjrx55ks5tbh3x08ln6wh0000gn/T/go-build60378254=/tmp/go-build -gno-record-gcc-switches -fno-common"
# 没有设置网络上的GOROOT、GOPATH等环境变量
fh@Feihu-3 go % echo $GOROOT
fh@Feihu-3 go % echo $GOPATH
fh@Feihu-3 go %
build.shgoland
GO111MODULE # 当前使用go.mod,配置为on
GOMODCACHE # 修改,否则会从默认的去找
GOPROXY # 必须修改,否则下载会遇到问题
GOPATH # 当前使用go.mod,不修改
代码结构
tree
RMB
fh@Feihu-3 RMB % tree
.
├── build
│ └── darwin
│ └── amd64
│ └── bin
│ ├── dn
│ ├── glog_demo
│ └── meta
├── pkg
│ └── mod
│ ├── cache
│ │ └── download
│ │ └── github.com
│ │ └── golang
│ │ └── glog
│ │ └── @v
│ │ ├── list
│ │ ├── list.lock
│ │ ├── v1.0.0.info
│ │ ├── v1.0.0.lock
│ │ ├── v1.0.0.mod
│ │ ├── v1.0.0.zip
│ │ └── v1.0.0.ziphash
│ └── github.com
│ └── golang
│ └── glog@v1.0.0
│ ├── LICENSE
│ ├── README.md
│ ├── glog.go
│ ├── glog_file.go
│ ├── glog_test.go
│ └── go.mod
└── src
├── base
│ └── log
│ └── log.go
├── build.sh
├── cmd
│ ├── demo
│ │ └── glog_demo.go
│ └── server
│ ├── dn.go
│ ├── meta.go
│ └── version.go
├── go.mod
└── go.sum
21 directories, 24 files
RMB
# RMB下分为三个目录:
# src:存放自己编写的代码
# pkg: 第三方包
# build:生成的可执行文件
# 其中功能如下:
# 1. 调用glog第三方库,编写glog_demo,路径是RMB/build/darwin/amd64/bin/glog_demo
# 2. 生成meta可执行文件,路径是RMB/build/darwin/amd64/bin/meta
# 3. 生成dn可执行文件,路径是RMB/build/darwin/amd64/bin/dn
# 4. 在编译的时候,自动将git的信息、构建日期等传递到可执行文件中
# 5. 封装go语言的log,并测试
开发流程
RMB
RMB
RMBgo init rmbgo.modgo.modbuildgo.modgo.sum
mainbuild.sh
mainbuild.sh
# version.go隶属于main包
# meta.go、dn.go和version必须要放到同一个目录下
# 同一个包调用不同文件问题,后面继续说
fh@Feihu-3 RMB % ls src/cmd/server/*
src/cmd/server/dn.go src/cmd/server/meta.go src/cmd/server/version.go
#! /bin/bash
# 执行的命令中,返回非0错误码即退出,不再执行后面内容
set -e
# 增加调试信息,执行的时候会打印所有的信息,真实环境会注释掉
set -x
# build.sh放在src目录下,获取RMB/src的路径
PROJ_SRC="$(cd "$(dirname "$0")"; pwd -P)"
# src目录的上级就是RMB路径
PROJ_ROOT="$(cd "$(dirname "$PROJ_SRC")"; pwd -P)"
# build路径: RMB/build
PROJ_BUILD=${PROJ_ROOT}/build
# 环境变量设置,通过go env GOROOT获取
export GOROOT=$(go env GOROOT)
# 下载包路径,默认是下载失败的,主要是给go get使用
export GOPROXY=https://goproxy.io
# 下载的第三方包路径,并自动从这里查找
export GOMODCACHE=${PROJ_ROOT}/pkg/mod
# 开启模块
export GO111MODULE="on"
# 清空RMB/build目录
rm -rf "${PROJ_BUILD}"
mkdir -p "${PROJ_BUILD}"
# 代码格式化,例如:Tab、大括号等格式
# 帮助可查gofmt -h
gofmt -l -w -s "${PROJ_SRC}"
# 标记,通过脚本将这些信息扔到代码里面去
# 这段代码来自etcd的Makefile,并加以修改,其实也只是version.go里面传参数
# 内容是:软件版本、GO系统、GO架构、git的提交、构建日期、go版本、构建者
# 由于本人未使用git,请将gitCommit的值换成下面提到的命令即可
LD_FLAGS=" \
-X main.rmbBuilderVersion='1.3.2' \
-X main.goos=$(go env GOOS) \
-X main.goarch=$(go env GOARCH) \
-X main.gitCommit='adfjlkdf' \
-X main.buildDate=$(date +'%Y-%m-%dT%H:%M:%SZ') \
-X main.goversion=$(go env GOVERSION) \
-X main.builder=$(whoami) \
"
# -o: 生成的可执行文件路径,RMB/build/darwin/amd64/bin/meta
# -a: 强制重新构建包
# -race: 开启数据竞态检测
# 注意: go build的最后一项是main函数所在的文件以及version文件
# 不增加version.go会失败,因为version.go里面的符号未提前生成,导致查询失败
go build -o "${PROJ_BUILD}"/$(go env GOHOSTOS)/$(go env GOHOSTARCH)/bin/meta \
-a \
-race \
-ldflags "-X main.buildDate=$(date +'%Y-%m-%dT%H:%M:%SZ') \
-X main.goos=$(go env GOOS) \
-X main.goarch=$(go env GOARCH) \
" \
"${PROJ_SRC}"/cmd/server/version.go "${PROJ_SRC}"/cmd/server/meta.go
go build -o "${PROJ_BUILD}"/$(go env GOHOSTOS)/$(go env GOHOSTARCH)/bin/dn \
-a \
-race \
-ldflags "${LD_FLAGS}" \
"${PROJ_SRC}"/cmd/server/version.go "${PROJ_SRC}"/cmd/server/dn.go
go build -o "${PROJ_BUILD}"/$(go env GOHOSTOS)/$(go env GOHOSTARCH)/bin/glog_demo \
-a \
-race \
"${PROJ_SRC}"/cmd/demo/glog_demo.go
LD_FLAGS=-ldflags " \
-X main.kubeBuilderVersion=$(shell git describe --tags --dirty --broken) \
-X main.goos=$(shell go env GOOS) \
-X main.goarch=$(shell go env GOARCH) \
-X main.gitCommit=$(shell git rev-parse HEAD) \
-X main.buildDate=$(shell date -u +'%Y-%m-%dT%H:%M:%SZ') \
"
下载第三方包
我们在配置好了之后,一般是先提前下载第三方包,再去写代码,因为我们需要有代码提示,例如:
# 下载的包路径根据GOMODCACHE 来确定
# 后面查找的时候,也是从GOMODCACHE来找
# 所以,需要在环境变量里面设置GOMODCACHE路径
go get github.com/golang/glog
demo
package main
import (
"flag"
"fmt"
"github.com/golang/glog"
)
func main() {
flag.Parse()
defer glog.Flush()
glog.Info("Fish")
glog.Infof("I like fish, value: %v", "mnkojj")
fmt.Println("xx")
}
本工程代码的连接如下:
# 之前写的,可根据编译脚本来做调整
https://download.csdn.net/download/wfh2015/21710635
编译结果:
fh@Feihu-3 src % ./build.sh
go: downloading github.com/golang/glog v1.0.0 # 在有网却缺少库的情况,自动下载
fh@Feihu-3 src % tree ../build
../build
└── darwin
└── amd64
└── bin
├── dn
├── glog_demo
└── meta
3 directories, 3 files
fh@Feihu-3 src % go mod tidy
fh@Feihu-3 src % go mod verify
all modules verified
fh@Feihu-3 src % go mod graph
rmb github.com/golang/glog@v1.0.0
fh@Feihu-3 src % go mod why
fh@Feihu-3 src %
至于其他的命令像什么,就不用说了:
go mod tidy
go mod graph
go mod verify
go mod graphv
GOMODCACHERMB
目前来看,不需要手动修改配置文件,基本满足在内网运行、DevOps运行的要求。
问题同一个包调用不同文件的接口会报错
这个问题解决方法有两类:
# 脚本:
# 只需要将两个go文件同时放到go build 中即可,参考前面的build.sh脚本
# goland
# 1. [打开编辑配置] -> [运行种类] -> [文件]
# 2. [文件]所在行的[展开]按钮,增加多个文件,增加之后,编辑栏会有‘|’符号区分不同路径