Go 语言是使用包(package)作为基本单元来组织源码的, Go 程序就是这些包链接起来而构建的。与C 语言的头文件包含机制相比则是“先进”了许多。

即便是每次编译都是从头开始。避免了 C 语言那种通过头文件分析依赖的巨大开销。Go 语言以包为基本构建单元的构建模型,依赖分析非常简单。

一 构建过程

Go 编译速度快从三个方面分析:

1.Go 要求每个源文件在开头处显式地import所有依赖的包,Go编译器不必读取和处理整个文件就可以确定其依赖的包列表;

2.Go 要求包之间不能存在循环依赖。由于无环,包可以被单独编译,也可以并行编译;

3.已编译的 Go 包对应的目标文件(xxx.o 或 xxx.a)中,如下

1) 该包本身的导出符号信息。

2) 还记录了其所依赖包的导出符号信息。

这样,Go编译器在编译某包M时,针对M依赖的每个包导入(比如:导入包N),只需读取一个目标文件即可(比如:N包编译成的目标文件,该目标文件中已经包含了N包的依赖包的导出信息),而无需再读取其他文件中的信息了。

通过 package 关键字声明 Go 源文件所属的包:

// xx.go package x ... …

上述源码表示:文件 xx.go 是包 x 的一部分。

使用 import 关键字导入依赖的标准库包或第三方包:

import (     "fmt"     // 标准库包导入     “x/y/z"  // 第三方包导入 ) func main() {     z.FuncName()     fmt.Println("Go!Go!Go!") }

看到上面代码都会想到将import后面的”z”、“fmt”与z.FuncName()和fmt.Println()中的z和fmt认同一个语法元素:包名。 但是以后深入学习Go语言后,发现并非这样。比如实施分布式消息框架nsq提供的官方client包时,包导入如下:

import “github.com/nsqio/go-nsq”

但是使用导出函数的时候,我们不是go-nsq.FuncName(),而是nsq.FuncName:

consumer,_:=nsq.NewConsumer("write_order", "ch", config)

你可能会问最后一个分段到底代表什么?是包名称?是一个路径?

Go程序构建过程和其他主流静态编译语言一样,Go语言的程序构建简单说是由编译(compile)和链接(link)两个阶段。

一个非main包在编译后会对应生成一个.a文件,该文件可以理解为是Go包的目标文件(是通过 pack 工具($GOROOT/pkg/tool/darwin_amd64/pack)对.o文件打包后形成的.a).默认情况下在编译过程中.a文件生成临时目录下,除非使用go install安装到$GOPATH/pkg下(Go1.11版本前),否则你看不到.a文件。如果构建可执行程序,那么.a文件会在构建可执行程序的链接阶段起使用。

标准库包的源码文件在$GOROOT/src 下面,而对应的 .a 文件存放在$GOROOT/pkg/darwin_amd64 下(以 MacOS 上为例;如果是 linux,则是 linux_amd64)

那么构建Go程序时,编译器会重新编译依赖包的源文件还是直接链接包的.a文件呢?

在使用第三方包的时候,当第三方包源代码存在且对应的.a已安装的情况下,编译器链接的仍是根据第三方包最新源代码编译出来的.a文件,而不是之前已经安装到

$GOPATH/pkg/darwin_amd64 下面的目标文件。

那Go 标准库中的包也是这样的吗?

默认情况下对于标准库中的包,编译器直接链接的是$GOROOT/pkg/darwin_amd64下的.a文件。

二 路径名?包名?

通过上面的知识,知道了编译器在编译过程中必然要使用的是编译单元(包)所依赖的包的源码。而编译器要找到依赖包的源码文件就需要知道依赖包的源码路径。这个路径由两部分组成:

1.基础搜索路径

2.包导入路径

基础搜索包是一个全局的设置,下面介绍一下:

所有包(标准库还是第三方包)的源码基础搜索路径都包括 $GOROOT/src

在上述基础搜索路径的基础上,不同版本的基础搜索路径有不同:

1.11 之前

$GOPATH/src

1.11-1.12 有三种:

经典gopath模式,GO111MODULE=off , $GOPATH/src

module-aware 模式,GO111MODULE=on, $GOPATH/pkg/mod

auto 模式,GO111MODULE=auto,在$GOPATH/src 路径下,与 gopath 模式相同;在$GOPATH/src 路径外且包含 go.mod,与 module-aware 模式相同。

1.13 有两种

经典gopath 模式,GO111MODULE=off,$GOPATH/src

module-aware 模式下,GO111MODULE=on/auto,$GOPATH/pkg/mod;

1.13后 

只有 module-aware 模式,即只在 module 缓存的目录下搜索包的源码。

搜索路径第二部分,是位于每个包源码文件头部的包导入路径。基础搜索路径与包导入路径结合在一起,Go编译器就可以确定一个包的所有依赖包的源码路径的集合,这样集合构成了Go编译器的源码搜索路径空间。

三 同一源码的依赖包在同一源码搜索路径下包名冲突,怎么办? 

package main import (         "github.com/xxx/p1/pkg/pkg11"         “github.com/xxx/p2/pkg/pkg11" ) func main() {         pkg1.Func1() } 

当你有这样的import的时候,运行main,直接报错。会告诉你包冲突。如何解决呢?

package mainimport (        p1 "github.com/xxx/p1/pkg/pkg11"        p2 “github.com/xxx/p2/pkg/pkg11")func main() {        p1.Func1()        p2.Func1()}

这样就ok了,解决了问题。

access导入链接快还是导入表快_Go 语言设计哲学之十三:理解包导入路径的含义...相关推荐

  1. 笔记: 解决oracle impdp导入dmp时, 用户名和表空间与dmp中的不相同导致无法导入的问题

    解决oracle impdp导入dmp时, 用户名和表空间与dmp中的不相同导致无法导入的问题 impdp导入时, 需要增加两个特殊的参数 remap_schema 更改用户名 remap_schem ...

  2. sqlserver导入向导时提示外部表不是预期格式_Excel办公实操,导入本地数据,创建参数查询,就是简单...

    导入数据创建参数查询 在技巧73中已经介绍了使用Excel的"来自Microsoft Query"功能有选择地导入数据的方法,该功能使用了Microsoft Query技术,该技术 ...

  3. golang 理解包导入

    Golang使用包(package)这种语法元素来组织源码,所有语法可见性均定义在package这个级别,与Java .python等语言相比,这算不上什么创新,但与C传统的include相比,则是显 ...

  4. oracle删除导入的文件,oracle创建表空间,导入出文件,删除

    1.创建表空间(1-3步在sql plus 中执行) create tablespace SXCGGL_TBS datafile 'E:/oracle/sanxia/SXCGGL_TBS.dbf' s ...

  5. 网站SEO优化中导入链接有哪些作用?

    导入链接包括外链和友情链接,通过这些链接的建设使网站获得更高的权重,对于目标关键词的排名也是有所提升.做好导入链接的优化,也是很多优化人员的目标,那么在网站SEO优化中,导入链接又有哪些作用呢?接下来 ...

  6. mysq命令行导出sql_MySQL命令行导出、导入数据库,备份数据库表

    MySQL导出数据库/数据表 1.首先,将你MySQL安装目录,例如C:\Program Files\MySQL\MySQL Server 5.7\bin添加到你的系统环境变量PATH中: 2.导出数 ...

  7. mysql外部表不是预期格式_批量Excel数据导入Oracle数据库 导入excel错误:外部表不是预期的格式 解决方案...

    在asp.net网站中导出Excel文件后,再把文件导入到数据库中. 读取Excel文件时,打开连接出错. 错误为:外部表不是预期的格式 解决:检查了一下,导出的Excel是标准文件不是html,没错 ...

  8. 【唠叨两句】如何将一张树型结构的Excel表格中的数据导入到多张数据库表中...

    小弟昨天遇到一个相对比较棘手的问题,就像标题说的那样.如何将一张树型结构的Excel表格中的数据导入到多张数据库表中,在现实中实际是七张数据库表,这七张表之间有着有着相对比较复杂的主外键关系,对于我这 ...

  9. mysql中数据表如何关联_mysql 如何导入/导出2个关联表中的数据

    mysql 怎么导入/导出2个关联表中的数据 表一 id student 1 S1 2 S2 表二 id sid scord order 1 1 100 1 2 1 60 2 3 1 80 3 4 2 ...

最新文章

  1. CodeGen API分析
  2. [探讨]一次性工具软件
  3. SpringBoot上传文件到本服务器 目录与jar包同级
  4. 【2016年第6期】情境大数据建模及其在用户行为预测中的应用
  5. 信息学奥赛一本通 1130:找第一个只出现一次的字符 | OpenJudge NOI 1.7 02
  6. 【社交分享SDK】ShareSDK for Android 2.5.9已经公布
  7. CCF推荐会议与期刊(人工智能 CV)
  8. 重庆兴渝计算机培训中心,重庆兴渝职业中等专业学校招生录取分数线
  9. Java读取图片 cmyk转rgb
  10. 若依源码分析(7)——岗位管理
  11. 【仪器常用操作方法】33500B函数发生器常用操作方法
  12. spfa - 黑暗城堡 - 一本通 3.1 例 1
  13. Gradle实现多渠道打包(不同资源文件打不同的包)
  14. html鼠标经过图片放大
  15. 旅游类小程序源码在哪下载?
  16. access连接机床_机床如何使用四大系统实现网络化管理
  17. matlab nag 工具箱,matlab 数值算法工具箱 NAG toolbox
  18. 3.1集合的概念和表示法
  19. CocosCreator 音效管理器
  20. SQL 把查询结果当作表来使用

热门文章

  1. 安装mysql5.5时常见错误--缺失make
  2. 呼叫中心的技术创新源于管理文化的变革
  3. easyui中combobox 验证输入的值必须为选项框中的数据
  4. 除非Microsoft FTP 服务(FTPSVC)正在运行,否则无法启动FTP站点。服务目前已停止...
  5. 什么是对象,为什么要面向对象,怎么才能面向对象?
  6. OOAD 面向对象分析与设计
  7. iqn怎么查 linux_程序员必备:46个Linux面试常见问题!收藏!
  8. spyder编辑器报ModuleNotFoundError: No module named ‘pymongo‘,明明已经安装上了pymongo扩展
  9. Python实现顺序表
  10. 写1行代码影响1000000000人,这是个什么项目?