学习go语言编程之工程管理
Go命令行工具
安装了Go语言的安装包后,就直接自带Go命令行工具。
# 查看当前安装的Golang版本
go version
# 查看go命令行工具的帮助信息
go help
Go命令行工具可以完成如下工作:
- 代码格式化
- 代码质量分析和修复
- 单元测试与性能测试
- 工程构建
- 代码文档的提取和展示
- 依赖包管理
- 执行其他的包含指令
代码风格
代码风格,是一个与人相关、与机器无关的问题。
代码风格的好坏,不影响编译器的工作,但是影响团队协同,影响代码的复用、演进以及缺陷修复。
强制性编码规范
命名
命名规则涉及变量、常量、全局函数、结构、接口、方法等的命名。
Go语言从语法层面进行了以下限定:任何需要对外暴露的名字必须以大写字母开头,不需要对外暴露的则应该以小写字母开头。
软件开发行业最流行的两种命名法分别为驼峰命名法和下划线法,Go语言明确宣告了拥护驼峰命名法而排斥下划线法。
排列
Go语言甚至对代码的排列方式也进行了语法级别的检查,约定了代码块中花括号的明确摆放位置。
非强制性编码风格建议
使用go fmt命令可以对代码进行格式化,例如:
# 格式化单个Golang源文件
go fmt hello.go
更详尽的用法可以查看:go help fmt。
当然,这个工具并非只能一次格式化一个文件,比如不带任何参数直接运行go fmt的话,可以直接格式化当前目录下的所有*.go文件,或者也可以指定一个GOPATH中可以找到的包名。
远程import支持
Go语言不仅允许我们导入本地包,还支持在语言级别调用远程的包。
假如,有一个用于计算CRC32的包托管于Github,那么可以这样写:
package main
import (
    "fmt"
    "github.com/myteam/exp/crc32"
)
在执行go build或者go install之前,只需要加这么一句:go get github.com/myteam/exp/crc32。
当执行完go get之后,会在src目录中看到github.com目录,其中包含myteam/exp/crc32目录。在crc32中,就是该包的所有源代码。
也就是说,go工具会自动获取位于远程的包源码,在随后的编译中,也会在pkg目录中生成对应的.a文件。
工程组织
GOPATH
Go命令行工具大部分功能其实不再针对当前目录,而是针对包名,于是如何才能定位到对应的源代码就落到了GOPATH环境变量身上。
假设现在本地硬盘上有3个Go代码工程,分别为~/work/go-proj1、~/work2/goproj2和~/work3/go-proj3,那么GOPATH可以设置为如下内容:
export GOPATH=~/work/go-proj1:~/work2/goproj2:~/work3/go-proj3
经过这样的设置后,就可以在任意位置对以上的3个工程进行构建。
目录结构
一个完整的Go项目工程结构通常如下:
<calcproj>
  - README
  - LICENSE
  - bin
    - calc
  - pkg
    - <linux_amd64>
      - simplemath.a
  - src
    - calc
      - calc.go
    - simplemath
      - add.go
      - add_test.go
      - sqrt.go
      - sqrt_test.go
Go语言工程不需要任何工程文件,一个比较完整的工程会在根目录处放置这样几个文本文件。
- README:简单介绍本项目目标和关键的注意事项,通常第一次使用时应该先阅读本文档。
- LICENSE:本工程采用的分发协议,所有开源项目通常都有这个文件。
一个标准的Go语言工程包含以下几个目录:src、pkg和bin。
src用于包含所有的源代码,这是Go命令行工具的一个强制的规则,而pkg和bin则无需手动创建,如果必要Go命令行工具在构建过程中会自动创建它们。
构建过程中Go命令行工具对包结构的理解完全依赖于src下面的目录结构。
文档管理
所谓的文档,更多的是指代码中的注释、函数、接口的输入、输出、功能和参数说明,这些对于后续的维护和复用有着至关重要的作用。
Go语言让开发者完全甩掉注释语法的包袱,专注于内容。
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Package foo implements a set of simple mathematical functions. These comments are for
demonstration purpose only. Nothing more.
If you have any questions, please don’t hesitate to add yourself to
golang-nuts@googlegroups.com.
You can also visit golang.org for full Go documentation.
*/
package foo
import "fmt"
// Foo compares the two input values and returns the larger
// value. If the two values are equal, returns 0.
func Foo(a, b int) (ret int, err error) {
    if a > b {
        return a, nil
    } else {
        return b, nil
    }
    return 0, nil
}
// BUG(jack): #1: I'm sorry but this code has an issue to be solved.
// BUG(tom): #2: An issue assigned to another person.
如上代码文档示例中,添加了4条注释:版权说明注释、包说明注释、函数说明注释和最后添加的遗留问题说明。
关于注释的编写,要遵守如下的基本规则:
- 注释需要紧贴在对应的包声明和函数之前,不能有空行。
- 注释如果要新起一个段落,应该用一个空白注释行隔开,因为直接换行书写会被认为是正常的段内折行。
- 开发者可以直接在代码内用// BUG(author):的方式记录该代码片段中的遗留问题,这些遗留问题也会被抽取到文档中。
工程构建
使用go build命令来执行构建,它会在你运行该命令的目录中生成工程的目标二进制文件,而不产生其他结果。
如果项目工程路径已经被加入到了全局变量GOPATH中,可以在任意位置执行go build命令,而不必关心是否能找到源代码。
注意: 在构建可执行程序工程时,会在当前所在的目录中生成可执行程序,所以通常选择在项目目录下的bin目录中执行构建。
构建示例如下:
# calc是项目src目录下的包名
go build calc
单元测试
Golang本身提供了一套轻量级的测试框架,符合规则的测试代码会在运行测试时被自动识别并执行。
单元测试源文件的命名规则如下:在需要测试的包下面创建以“_test”结尾的go文件,形如[^.]*_test.go。
Golang的单元测试函数分为两类:功能测试函数和性能测试函数,分别为以Test和Benchmark为函数名前缀并以*testing.T或*testing.B为单一参数的函数。
示例如下:
// 功能测试函数以Test为函数名前缀
func TestAdd1(t *testing.T)
// 性能测试函数以Benchmark为函数名前缀
func BenchmarkAdd1(t *testing.B)
测试工具会根据函数中的实际执行动作得到不同的测试结果:功能测试函数会根据测试代码执行过程中是否发生错误来返回不同的结果,而性能测试函数仅仅打印整个测试过程的花费时间。
功能单元测试
功能单元测试示例代码:
func TestAdd(t *testing.T) {
	r := Add(1, 2)
	if r != 3 {
		t.Errorf("Add(1,2) failed. Got %d, expected 3.", r)
	}
}
执行功能单元测试非常简单,直接执行go test命令即可。
# 执行当前所在包的所有单元测试
go test
当然,也可以在IDE中对单个方法执行单元测试。
性能单元测试
性能单元测试示例代码:
func BenchmarkAdd(b *testing.B) {
	for i := 0; i < b.N; i++ {
		Add(1, 2)
	}
}
性能测试与功能测试代码相比,最大的区别在于代码里的这个for循环,写这个for循环的原因是为了能够让测试运行足够长的时间便于进行平均运行时间的计算。
如果测试代码中一些准备工作的时间太长,也可以这样处理以明确排除这些准备工作所花费时间对于性能测试的时间影响:
func BenchmarkAdd(b *testing.B) {
    b.StopTimer()   // 暂停计时器
    DoPreparation() // 一个耗时较长的准备工作,比如读文件
    b.StartTimer()  // 开启计时器,之前的准备时间未计入总花费时间内
	for i := 0; i < b.N; i++ {
		Add(1, 2)
	}
}
学习go语言编程之工程管理的更多相关文章
- Go语言 函数,工程管理
		Go语言 函数,工程管理 1.无参无返回值函数的使用 package main import "fmt" func main() { // 无参无返回值函数的调用:函数名() fu ... 
- Golang编程的工程管理
		Golang编程的工程管理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 
- go语言基础之工程管理和工作区介绍
		1.工程管理 在实际的开发工作中,直接调用编译器进行编译和链接的场景是少而又少,因为在工程中不会简单到只有一个源代码文件,且源文件之间会有相互的依赖关系.如果这样一个文件一个文件逐步编译,那不亚于一场 ... 
- 学习go语言编程系列之helloworld
		1. 下载https://golang.org/dl/ # Go语言官网地址,在国内下载太慢,甚至都无法访问.通过如下地址下载:https://golangtc.com/download. 2. 安装 ... 
- 如何轻松学习C语言编程!
		C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ... 
- 学习go语言编程系列之定义变量
		package main import ( "fmt" "math") func main() { // 1. 定义变量名age,不初始化,使用对应类型的默认值 ... 
- go语言20小时从入门到精通(六、工程管理)
		在实际的开发工作中,直接调用编译器进行编译和链接的场景是少而又少,因为在工程中不会简单到只有一个源代码文件,且源文件之间会有相互的依赖关系.如果这样一个文件一个文件逐步编译,那不亚于一场灾难. Go语 ... 
- Linux下C语言编程基础学习记录
		VIM的基本使用 LINUX下C语言编程 用gcc命令编译运行C语言文件 预处理阶段:将*.c文件转化为*.i预处理过的C程序. 编译阶段:将*.i文件编译为汇编代码*.s文件. 汇编阶段:将*.s ... 
- Linux C语言编程学习笔记 (1)进程控制入门
		想进行Linux系统开发已经很久了,一直没有付诸实践.今日终于开始学习Linux下的C语言编程,研究一天,终于大概弄明白了Linux系统进程管理的一些基本概念和编程方法,总结下来以方便大家学习和自己实 ... 
- go语言入门(5)工程管理
		在工程中不会简单到只有一个源代码文件,且源文件之间会有相互的依赖关系,早期Go语言使用makefile作为工程管理的临时方案,后来的Go命令行工具的革命性之处在于彻底消除了工程文件的概念,完全用目录结 ... 
随机推荐
- [转帖]clickhouse存储机制以及底层数据目录分布
			https://www.cnblogs.com/MrYang-11-GetKnow/p/15818141.html#:~:text=%E6%AF%8F%E4%B8%80%E4%B8%AA%E6%95% ... 
- [转帖]Shell字符串拼接(连接、合并)
			http://c.biancheng.net/view/1114.html 在脚本语言中,字符串的拼接(也称字符串连接或者字符串合并)往往都非常简单,例如: 在 PHP 中,使用.即可连接两个字符串: ... 
- ebpf的简单学习
			ebpf的简单学习-万事开头难 前言 bpf 值得是巴克利包过滤器 他的核心思想是在内核态增加一个可编程的虚拟机. 可以在用户态定义很多规则, 然后直接在内核态进行过滤和使用. 他的效率极高. 因为避 ... 
- JVM内存配置的再次思考
			JVM内存配置的再次思考 摘要 最近研究过不少内存分配相关的处理 今天晚上突然感觉还不是非常系统. 还是想能够细致的在学习一下. 希望能够慢慢的拾遗,提高自己 操作系统内存的使用情况 本文主要想思考l ... 
- OpenEuler2203使用rpm方式安装Oracle19c的过程
			OpenEuler2203使用rpm方式安装Oracle19c的过程 安装介质 oracle-database-preinstall-19c-1.0-1.el7.x86_64.rpm oracle-d ... 
- flask session 伪造
			flask session 伪造 一.session的作用 由于http协议是一个无状态的协议,也就是说同一个用户第一次请求和第二次请求是完全没有关系的,但是现在的网站基本上有登录使用的功能,这就要求 ... 
- ChatGPT 中,G、P、T 分别是什么意思?
			流行的技术名词按发音难度排序,ChatGPT 肯定排在前面. 到底它为什么叫做 ChatGPT 呢? 先说 GPT:Generative Pre-Training Transformer Genera ... 
- Windows10磁盘占用100%和内存占用高
			前言 公司配备了两台电脑,两台电脑都是安装的win10系统,一台是磁盘占用高,另一台是内存可用低. 具体情况如下: 一台外网机 8g内存,安装win10 专业版,开机一天后经常出现内存不够用,但其实都 ... 
- 从零开始配置vim(28)——DAP 配置
			首先给大家说一声抱歉,前段时间一直在忙换工作的事,包括但不限于交接.背面试题准备面试.好在最终找到了工作,也顺利入职了.期间也有朋友在催更,在这里我对关注本系列的朋友表示感谢.多的就不说了,我们正式进 ... 
- 4.5 C++ Boost 文件目录操作库
			Boost 库是一个由C/C++语言的开发者创建并更新维护的开源类库,其提供了许多功能强大的程序库和工具,用于开发高质量.可移植.高效的C应用程序.Boost库可以作为标准C库的后备,通常被称为准标准 ... 
