Go 语言基础入门系列教程 —— Go 项目基本工程管理示例

栏目: PHP · 发布时间: 5年前

内容简介:在上一篇教程中,学院君带着大家搭建起了本地开发环境,并且编写了第一个 Go 程序,向世界问好。不过在实际开发过程中,直接调用编译器进行编译和链接(调用Go 语言的设计者作为行业老将,自然不会忽略这一点。说到这里,我们来看看 Go 语言的主要设计者都是何方神圣:

工程管理概述

在上一篇教程中,学院君带着大家搭建起了本地开发环境,并且编写了第一个 Go 程序,向世界问好。不过在实际开发过程中,直接调用编译器进行编译和链接(调用 go buildgo run 命令)的场景很少,因为在项目工程中不会简单到只有一个源文件,往往有很多源文件并且源文件之间会有相互依赖的关系,如果这样一个文件一个文件逐步编译,那简直无法想象。

Go 语言的设计者作为行业老将,自然不会忽略这一点。说到这里,我们来看看 Go 语言的主要设计者都是何方神圣:

Go 语言基础入门系列教程 —— Go 项目基本工程管理示例

个顶个的都是大神级人物。早期 Go 语言使用 makefile 作为临时方案,到了 Go 1 发布时引入了强大无比的 Go 命令行工具 ,Go 命令行 工具 彻底消除了工程文件的概念,完全用目录结构和包名来推导工程结构和构建顺序。想想 C 语言编译、链接和安装可执行程序的繁琐步骤,首先要通过 configure 脚本对特定平台进行检测,比如是否包含 GCC 等编译工具,然后生成 Makefile 文件,该文件定义了编译、链接规则,为下一步编译工作做准备,接下来就是执行 make 命令进行编译工作,最后再执行 make install 命令完成应用程序的安装,经历过这些步骤才可以实现将 C 程序源代码编译为可执行程序。

与之相比,Go 语言则要简单的多,针对只有一个源文件的情况(如上篇教程所示),引入工程管理看起来比较多余,因为直接用 go rungo build 搞定,下面我们通过 Go 语言构建一个简单的计算器项目来演示 Go 语言的基本工程管理方法。

编写计算器工程源码

我们假设这个工程被划分为两个部分:

  • 可执行程序,名为 calc ,内部只包含一个 calc.go 文件,该文件是计算器程序的入口文件;
  • 算法库,名为 simplemath ,每个计算操作对应于一个同名的 Go 文件,比如 add.go 用于计算加法运算。

这样,对应的工程目录组织应该如下所示:

Go 语言基础入门系列教程 —— Go 项目基本工程管理示例

然后我们来编写每个 Go 文件的源代码, src/calc/calc.go 的源码如下:

package main

// 引入其它包
import (
    "fmt"
    "os"
    "simplemath"
    "strconv"
)

// 定义一个用于打印程序使用指南的函数
var Usage = func() {
    fmt.Println("USAGE: calc command [arguments] ...")
    fmt.Println("\nThe commands are:\n\tadd\t计算两个数值相加\n\tsqrt\t计算一个非负数的平方根")
}

// 程序入口函数
func main ()  {
    /*
     * 用于获取命令行参数,注意程序名本身是第一个参数,
     * 比如 calc add 1 2 这条指令,第一个参数是 calc
     */
    args := os.Args
    // 除程序名本身外,至少需要传入两个其它参数,否则退出
    if args == nil || len(args) < 3 {
        Usage()
        return
    }

    // 第二个参数表示计算方法
    switch args[1] {
        // 如果是加法的话
        case "add":
            // 至少需要包含四个参数
            if len(args) != 4 {
                fmt.Println("USAGE: calc add <integer1><integer2>")
                return
            }
            // 获取待相加的数值,并将类型转化为整型
            v1, err1 := strconv.Atoi(args[2])
            v2, err2 := strconv.Atoi(args[3])
            // 获取参数出错,则退出
            if err1 != nil || err2 != nil {
                fmt.Println("USAGE: calc add <integer1><integer2>")
                return
            }
            // 从 simplemath 包引入 Add 方法进行加法计算
            ret := simplemath.Add(v1, v2)
            // 打印计算结果
            fmt.Println("Result: ", ret)
        // 如果是计算平方根的话
        case "sqrt":
            // 至少需要包含三个参数
            if len(args) != 3 {
                fmt.Println("USAGE: calc sqrt <integer>")
                return
            }
            // 获取待计算平方根的数值,并将类型转化为整型
            v, err := strconv.Atoi(args[2])
            // 获取参数出错,则退出
            if err != nil {
                fmt.Println("USAGE: calc sqrt <integer>")
                return
            }
            // 从 simplemath 包引入 Sqrt 方法进行平方根计算
            ret := simplemath.Sqrt(v)
            // 打印计算结果
            fmt.Println("Result: ", ret)
        // 如果计算方法不支持,打印程序使用指南
        default:
            Usage()
    }
}

这段代码相信对于有 PHP 编程基础的人来说,都不困难,需要注意的是在 Go 语言中,通过 var 来声明变量,并且可以将匿名函数赋值给变量以便后续使用,此外,还可以通过 := 运算符来声明并初始化变量,这个时候,不需要通过 var 声明该变量,比如 args := os.Args 就是如此,需要明确的是,虽然看起来有点和动态语言声明变量类似,但与 PHP 不同,Go 是强类型语言,只不过底层会自动根据赋值判断对应变量的类型,如果你试图声明一个没有初始化值的变量,就会报错,关于 Go 语言变量声明和初始化我们后面还会详细介绍,这里简单了解下即可。

接下来,我们编辑 src/simplemath/add.go 代码如下:

package simplemath

func Add(a int, b int) int {
    return a + b
}

以及 src/simplemath/sqrt.go 代码如下:

package simplemath

import "math"

func Sqrt(i int) int {
    v := math.Sqrt(float64(i))
    return int(v)
}

配置 GOPATH 环境变量

为了能够构建这个工程,需要先把这个工程的根目录加入到环境变量 GOPATH 中,上篇教程中,我们介绍过 GOPATH ,并且提到其默认值是 ~/go (其中 ~ 表示用户家目录),除此之外,我们还可以为 GOPATH 配置多个路径值,以便我们在任意地方组织编写 Go 项目代码。假设计算器项目根目录 calc 目录位于 ~/go 下,如果是基于 GoLand 进行开发的话,可以通过「首选项(Preferences)->Go->GOPATH」界面来进行设置:

Go 语言基础入门系列教程 —— Go 项目基本工程管理示例

在 Project GOPATH 中新增一条路径即可,然后点击「Apply」按钮,很简单。此外,在 Unix-Like 系统中,还可以通过编辑 ~/.bashrc 文件,并添加下面这行代码:

export GOPATH=~/go/calc

然后执行以下命令应用该设置来完成 GOPATH 的自定义设置:

$ source ~/.bashrc

在 Windows 中,则可以通过配置环境变量 GOPATH 来实现,将你的项目根目录完整路径拷贝过去就好

了。和 PATH 环境变量一样, GOPATH 也可以支持一次配置多个路径,并且路径和路径之间用冒号分隔。

GOPATH 的用处是 Go 语言在编译程序时,会从 GOPATH 配置的路径里面去查找源文件并完成构建。

构建 Go 工程

设置完 GOPATH 后,现在我们开始构建工程。假设我们希望把生成的可执行文件放到 calc/bin 目录中,需要执行的一系列指令如下:

cd ~/go/calc
mkdir bin 
cd bin
go build calc

这样就会在 calc/bin 目录下生成可执行文件 calc

Go 语言基础入门系列教程 —— Go 项目基本工程管理示例

然后我们就可以执行 calc 程序了:

Go 语言基础入门系列教程 —— Go 项目基本工程管理示例

从上面的构建过程中可以看到,真正的构建命令就一句:

go build calc

这就是为什么说 Go 命令行工具是非常强大的。我们不需要写 makefile ,因为这个工具会替我们分析,知道目标代码的编译结果应该是一个包还是一个可执行文件,并分析 import 语句以了解包的依赖关系,从而在编译 calc.go 之前先把依赖的 simplemath 编译打包好。Go 命令行程序制定的目录结构规则让代码管理变得非常简单。

当然,这里只是一个最简单、最基本工程管理的构建示例,后面我们还会就更复杂的工程项目管理进行介绍,比如工程组织、文档与代码风格、跨平台开发、单元测试、打包分发等。学习过程中有任何问题,欢迎通过下面的评论或加入社群与我讨论。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Machine Learning

Machine Learning

Kevin Murphy / The MIT Press / 2012-9-18 / USD 90.00

Today's Web-enabled deluge of electronic data calls for automated methods of data analysis. Machine learning provides these, developing methods that can automatically detect patterns in data and then ......一起来看看 《Machine Learning》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

MD5 加密
MD5 加密

MD5 加密工具

SHA 加密
SHA 加密

SHA 加密工具