Go 编译构建的一些细节

Go 编译构建的一些细节

发现自己竟然没有怎么认真研究过 go 的编译构建命令。

结论前置

  • go run 专门用来运行命令源码文件的命令,一般用来运行单个文件
  • go build 主要是用于测试编译。编译某个包或者项目,在当前目录下生成可执行文件
  • go install 编译并安装代码包或者源码文件的。
  • go get 用于从远程代码仓库(比如 Github )上下载代码包并更新 mod
  • go 1.17 之后 go get 只下载源码,并将依赖添加到 go.mod。get install 用来下载和安装三方库

go 命令常用选项

在这里插入图片描述

下面是细节。

go run

专门用来运行命令源码文件的命令,不是用来运行所有 go 源码文件的

go run 命令只能接受一个命令源码文件以及若干个库源码文件(必须同属于 main 包)作为文件参数,且不能接受测试源码文件。它在执行时会检查源码文件的类型。如果参数中有多个或者没有命令源码文件,那么 go run 命令就只会打印错误提示信息并退出,而不会继续执行。

go run -ngo run 命令的一个选项,用于执行编译和运行 Go 源文件,但不实际运行。它会打印出编译时将要执行的命令,而不会真正运行该命令。这对于调试构建脚本或查看编译命令是否正确非常有用。

  1. 临时文件生成: 在使用 go run 命令时,会生成临时工作目录(通常在系统的临时目录下),其中包含编译过程中产生的临时文件和中间文件。
  2. 导入文件(importcfg 文件): importcfg 文件用于指定程序在编译时所需的导入包。这个文件在编译过程中被使用,而不是在运行时。
  3. compile 命令和生成 link 文件: 在编译过程中,compile 命令用于将源码文件编译成归档文件(archive)。生成的 link 文件记录了编译过程中用到的依赖信息。
  4. 生成可执行文件: 最后,exe 文件是通过连接编译生成的归档文件和 link 文件,并将其与源码文件一起打包成可执行文件。
  5. go run 命令生成的文件: go run 命令会在执行过程中生成两个文件,一个是编译生成的归档文件(通常具有 .a 扩展名),另一个是最终的可执行文件。

举例:

go run app/user/*.go

等价于什么呢?

go run app/user/*.go 命令用于直接运行指定目录下的所有 Go 源代码文件。它的等价操作包括:

  1. 编译并运行每个 .go 文件中的代码。
  2. 如果代码中有 main 函数,则执行该函数;如果没有,则不执行。
  3. 该命令只在开发阶段使用,不会生成可执行文件,而是临时编译和执行代码。

因此,go run app/user/*.go 与手动编译并执行每个文件的操作等价。

问题:会递归查找所有目录吗?

不会。go run app/user/*.go 只会在 app/user/ 目录下查找直接位于该目录下的 .go 文件,而不会递归查找其子目录中的文件。如果需要递归查找所有子目录中的 .go 文件,可以使用 ./... 来代替 *,例如 go run ./...go run ./... 是一个 Go 语言的命令,用于编译并运行当前目录(以及子目录)中的所有 Go 源码文件。这个命令会查找当前目录下的所有 .go 文件,并且假定它们属于同一个包,然后尝试编译它们。

这里的 ./... 是一个模式匹配表达式,用于匹配当前目录及其所有子目录中的所有文件和目录。在 Go 命令中,这种模式匹配通常用于指定源码文件的路径。

具体来说:

  • . 表示当前目录。
  • ...(三个点)是一个通配符,表示递归地匹配当前目录下的所有子目录。

因此,go run ./... 命令会执行以下操作:

  1. 编译当前目录及其所有子目录中的所有 .go 文件。
  2. 将编译后的代码链接成一个可执行文件。
  3. 运行这个可执行文件。

这个命令在处理包含多个源码文件的包时非常有用,尤其是当你想要快速运行和测试整个包中的代码时。然而,需要注意的是,这个命令不会递归地编译子目录中的子目录,它只编译当前目录及其直接文件和子目录中的 .go 文件。

如果你的 Go 项目结构中,每个功能或模块位于不同的包中,那么使用 go run ./... 可能不会按预期工作,因为它会尝试编译所有匹配到的源码文件,而不管它们是否属于同一个包。在这种情况下,你可能需要更精细地指定要编译的文件或目录。

再看 go build

另外,使用 dlv 进行远程调试的话,必须 build 出可执行文件 main 之后,才可以。

所以这个时候需要执行

go build -o main

然后运行就可以开始监听了。

在这里插入图片描述

区别于 go build main.go

区分 Go 编译单个文件和目录下所有文件

go build main.gogo build -o main 都是用于构建 Go 应用程序的命令,但它们之间有一些区别:

  1. go build main.go:这个命令告诉 Go 编译器要编译名为 main.go 的文件,并生成一个默认的可执行文件,文件名与包名相同(如果 main.go 中的包名是 main,则生成的可执行文件为 main)。
  2. go build -o main:这个命令告诉 Go 编译器要编译当前目录下的所有文件,并将生成的可执行文件命名为 main。使用 -o 标志可以指定生成的可执行文件的名称,而不是使用默认的包名。

总的来说,go build main.go 适用于单个文件的构建,而 go build -o main 适用于多个文件的构建,并且可以指定生成的可执行文件的名称。

  1. 用途: go build 命令主要用于编译测试。它会编译指定的源码文件或代码包及其依赖。

  2. 普通包 vs. main 包:

    • 对于普通包:执行 go build 后不会生成任何文件。
      举例:
      在这里插入图片描述
    • 对于 main 包:只执行 go build 会在当前目录下生成一个可执行文件。要在 $GOPATH/bin 目录下生成相应的可执行文件,需要执行 go install 或者使用 go build -o 路径/可执行文件
  3. 单文件 vs. 多文件:

    • 如果某个文件夹下有多个文件,而只想编译其中的某一个文件,可以在 go build 之后加上文件名,例如 go build a.go
    • 默认情况下,go build 会编译当前目录下的所有 go 文件。
  4. 指定输出文件名: 可以使用 -o 标志指定编译输出的文件名。默认情况下,输出文件名为包名(对于非 main 包)或第一个源文件的文件名(对于 main 包)。

  5. 忽略文件: go build 会忽略目录下以"_“或”."开头的 go 文件。

  6. 跨平台编译: 如果源代码需要针对不同的操作系统进行处理,可以根据不同的操作系统后缀来命名文件。

  7. 库源码文件编译: 对于库源码文件,go build 只会进行检查性的编译,而不会生成任何结果文件。

  8. 示例: 执行 go build 编译命令源码文件时,会在该命令的执行目录中生成一个可执行文件。如果跟了代码包导入路径作为参数,则该代码包及其依赖都会被编译。

  9. 执行过程: 类似于 go rungo build 在编译后会将生成的可执行文件重命名并移动到当前目录下。

参考:

https://zhuanlan.zhihu.com/p/619500945

go install 和 go get

go getgo install 是 Go 语言中两个常用的命令,它们虽然有一些相似之处,但在功能上有一些不同。

  1. go get:

    • go get 命令用于从远程仓库中获取并安装指定的包或模块。它通常用于获取项目的依赖项。
    • 如果执行 go get 命令时指定了包或模块的路径,它将尝试从远程仓库中下载该包或模块,并将其放置在 $GOPATH/src 目录下的相应位置。
    • go get 还会安装该包或模块所依赖的其他包或模块。
  2. go install:

    • go install 命令用于编译并安装指定的包或可执行文件。
    • 如果执行 go install 命令时指定了包的路径,它将编译该包并将生成的二进制文件安装到 $GOPATH/bin 目录(或 $GOBIN 目录)下。
    • 如果执行 go install 命令时指定了可执行文件的路径,它将编译该可执行文件并将生成的二进制文件安装到 $GOPATH/bin 目录(或 $GOBIN 目录)下。

在实践中,通常情况下,我们使用 go get 来获取项目的依赖项,而使用 go install 来构建并安装我们自己的代码或可执行文件。

go install 命令

  • 用途: 编译并安装代码包或者源码文件。

  • 流程: 分为两步:

    1. 第一步是生成结果文件(可执行文件或者.a 包)。
    2. 第二步是将编译好的结果移到 $GOPATH/pkg 或者 $GOPATH/bin
  • 可执行文件: 一般由带有 main 函数的 Go 文件产生,具有函数入口,可以直接运行。

  • .a 应用包: 一般由不包含 main 函数的 Go 文件产生,没有函数入口,只能被调用。

go get 命令

  • 用途: 从远程代码仓库(如 GitHub)下载并安装代码包。

  • 注意:

    • go get 命令将当前代码包下载到 $GOPATH 中的第一个工作区的 src 目录,并进行安装。
    • 从 Go 1.17 版本开始,go get 仅用于下载库和更新 mod 文件,并不会执行安装操作。

其他命令

go clean 命令是用来移除当前源码包里面编译生成的文件,这些文件包括

_obj/ 旧的 object 目录,由 Makefiles 遗留

_test/ 旧的 test 目录,由 Makefiles 遗留

_testmain.go 旧的 gotest 文件,由 Makefiles 遗留

test.out 旧的 test 记录,由 Makefiles 遗留

build.out 旧的 test 记录,由 Makefiles 遗留

*.[568ao] object 文件,由 Makefiles 遗留

DIR(.exe) 由 go build 产生

DIR.test(.exe) 由 go test -c 产生

MAINFILE(.exe) 由 go build MAINFILE.go 产生

go fmt 命令主要是用来帮你格式化所写好的代码文件。

go test 命令,会自动读取源码目录下面名为*_test.go 的文件,生成并运行测试用的可执行文件。默认的情况下,不需要任何的参数,它会自动把你源码包下面所有 test 文件测试完毕,当然你也可以带上参数,详情请参考 go help testflag

go doc 命令其实就是一个很强大的文档工具。

go fix 用来修复以前老版本的代码到新版本,例如 go1 之前老版本的代码转化到 go1

go version 查看 go 当前的版本

go env 查看当前 go 的环境变量

go list 列出当前全部安装的 package

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/821588.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ - Spring boot 整合 RabbitMQ

一、RabbitMQ 1、RabbitMQ 使用场景 1.1、服务解耦 假设有这样一个场景, 服务A产生数据, 而服务B,C,D需要这些数据, 那么我们可以在A服务中直接调用B,C,D服务,把数据传递到下游服务即可 但是,随着我们的应用规模不断扩大,会有更多的服务需要A的数据,如果有几十甚至几百个下…

【CANN训练营】目标检测(YoloV5s)实践(Python实现)

样例介绍 使用多路离线视频流(* .mp4)作为应用程序的输入,基于YoloV5s模型对输入视频中的物体做实时检测,将推理结果信息使用imshow方式显示。 样例代码逻辑如下所示: 环境信息 CPU:Intel Xeon Gold 63…

C++11新特性系列(一)

目录 1、C11简介 2、列表的初始化 2.1 {}初始化 2.2 initializer_list 3、auto与decltype 3.1 auto 3.2 decltype 4、范围for循环 5、右值引用和移动语义 4.1 左值引用和右值引用 4.1.1 左值引用 4.1.2 右值引用 4.2 右值引用使用场景和意义 1、C11简介 C11是C语言…

高通 Android 12 源码编译aidl接口

最近在封装系统sdk接口 于是每次需要更新aidl接口 ,传统方式一般使用make update-api或者修改Android.mk文件,今天我尝试使用Android.bp修改 ,Android 10之前在Android.mk文件修改,这里不做赘述。下面开始尝试修改,其实…

InnoDB架构:磁盘篇

InnoDB架构:磁盘篇 InnoDB是MySQL数据库中默认的存储引擎,它为数据库提供了事务安全型(ACID兼容)、行级锁定和外键支持等功能。InnoDB的架构设计优化了对于读取密集和写入密集型应用的性能表现,是一个高度优化的存储系…

近屿智能全新推出AI培训产品:AIGC大模型工程师与产品经理学习路径图

如今,人工智能和自然语言处理技术的发展,使得AI生成的内容(AIGC,AI Generated Content)领域开发出了巨大的潜力。就像业内巨头OpenAI公司,开发出了一系列自然语言处理模型ChatGPT,不仅带动了全世…

C语言单向链表的经典算法

1.分割链表 2.移除链表元素 3.反转链表 4.合并两个有序链表 5.链表的中间结点 6.环形链表的约瑟夫问题 1.分割链表: 1.思路:创建新链表,小链表和大链表。如图 代码如下 /*** Definition for singly-linked list.* struct ListNode {* int val…

Unity类银河恶魔城学习记录12-18,19 p140 Options UI-p141 Finalising ToolTip源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili UI_ToolTip.cs using TMPro; using UnityEngine;public class UI_ToolTip :…

IBM SPSS Statistics for Mac中文激活版:强大的数据分析工具

IBM SPSS Statistics for Mac是一款功能强大的数据分析工具,为Mac用户提供了高效、精准的数据分析体验。 IBM SPSS Statistics for Mac中文激活版下载 该软件拥有丰富的统计分析功能,无论是描述性统计、推论性统计,还是高级的多元统计分析&am…

【面试经典 150 | 链表】K 个一组翻转链表

文章目录 写在前面Tag题目来源解题思路方法一:迭代 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更…… 专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾…

【从零开始手搓12306项目】第一阶段遇到的问题及解决方案

IDEA中datebase连接mysql失败 读取外包函数报错 注意区分private和public 找不到数据库? 一定要注意数据库的url链接,在datebase的url复制过来 xml和java对应不上? 最好复制一遍到xml文件 git忽略条件文件目录 定义Git全局的 .gitigno…

人工智能与IP代理池:解析网络数据采集的未来

前言 随着互联网的快速发展,数据成为了当今社会最宝贵的资源之一。然而,要获取大量的网络数据并进行有效的分析,往往需要面对诸多挑战,其中之一就是网络封锁与反爬虫机制。在这个背景下,人工智能(AI&#x…

Python 物联网入门指南(七)

原文:zh.annas-archive.org/md5/4fe4273add75ed738e70f3d05e428b06 译者:飞龙 协议:CC BY-NC-SA 4.0 第二十四章:基本开关 到目前为止一定是一段史诗般的旅程!回想一下你开始阅读这本书的时候,你是否曾想象…

IP协议如何进行地址管理?

如今,IP协议有两个版本,分别是IPv4和IPv6,IPv4是目前主要应用的版本。IPv4的IP地址是以4个字节的数字来表示的,比如 127.0.0.1。因此,IPv4所能表示IP地址的个数是2^32次方,也就是42亿多个,看起来…

OpenStack 入门体验

目录 一、云计算概述 1.1、什么是云计算 1.2、云计算的服务模型 1)IaaS 2)PaaS 3)SaaS 1.3、OpenStack 概述 1)OpenStack 起源 2)什么是 OpenStack 3)OpenStack 优势 二、OpenStack 一…

RabbitMQ进阶学习

在之前的练习作业中,我们改造了余额支付功能,在支付成功后利用RabbitMQ通知交易服务,更新业务订单状态为已支付。 但是大家思考一下,如果这里MQ通知失败,支付服务中支付流水显示支付成功,而交易服务中的订…

IAM 统一身份认证与访问管理服务

即统一身份认证与访问管理服务,是云服务商提供的一套云上身份管理解决方案,可帮助企业安全地管理云上资源的访问权限。 在当今云计算时代,企业越来越依赖云服务来存储和处理敏感数据。然而,这也带来了新的安全挑战,即…

CentOS:执行make命令时报错g++: Command not found

报错截图: 其实很简单只需要安装一下 yum -y install gcc automake autoconf libtool make yum install gcc gcc-c

RabbitMQ交换机的类型

交换机类型 可以看到,在订阅模型中,多了一个exchange角色,而且过程略有变化: Publisher:生产者,不再发送消息到队列中,而是发给交换机 Exchange:交换机,一方面&#xff…

OSPF大型实验

OSPF大型实验 实验拓扑图 实验思路 1、R4为ISP,其上只配置IP地址;R4与其他所直连设备间均使用公有IP; 2、R3-R5、R6、R7为MGRE环境,R3为中心站点; 3、整个OSPF环境IP基于172.16.0.0/16划分;除了R12有两…