当前位置: 首页 > news >正文

橙子建站 推广重庆seo博客

橙子建站 推广,重庆seo博客,wordpress侧边栏加图片,深圳建筑工地招聘信息Go语言是使用包(package)作为基本单元来组织源码的,可以说一个Go程序就是由一些包链接在一起构建而成的。虽然与Java、Python等语言相比这算不上什么创新,但与祖辈C语言的头文件包含机制相比则是“先进”了许多。 编译速度快是这种…

Go语言是使用包(package)作为基本单元来组织源码的,可以说一个Go程序就是由一些包链接在一起构建而成的。虽然与Java、Python等语言相比这算不上什么创新,但与祖辈C语言的头文件包含机制相比则是“先进”了许多。

编译速度快是这种“先进性”的一个突出表现,即便每次编译都是从零开始。Go语言的这种以包为基本构建单元的构建模型使依赖分析变得十分简单,避免了C语言那种通过头文件分析依赖的巨大开销。

Go编译速度快的原因具体体现在以下三方面。

● Go要求每个源文件在开头处显式地列出所有依赖的包导入,这样Go编译器不必读取和处理整个文件就可以确定其依赖的包列表。

● Go要求包之间不能存在循环依赖,这样一个包的依赖关系便形成了一张有向无环图。由于无环,包可以被单独编译,也可以并行编译。

● 已编译的Go包对应的目标文件(file_name.o或package_name.a)中不仅记录了该包本身的导出符号信息,还记录了其所依赖包的导出符号信息。

这样,Go编译器在编译某包P时,针对P依赖的每个包导入(比如导入包Q),只需读取一个目标文件即可(比如:Q包编译成的目标文件中已经包含Q包的依赖包的导出信息),而无须再读取其他文件中的信息。
Go语言中包的定义和使用十分简单。通过package关键字声明Go源文件所属的包:

// xx.go
package a
...
上述源码表示文件xx.go是包a的一部分。
使用import关键字导入依赖的标准库包或第三方包:
package mainimport ("fmt" // 标准库包导入"a/b/c" // 第三方包导入
)
func main() {
c.Func1()
fmt.Println("Hello, Go!")
}

很多Gopher看到上面的代码会想当然地将import后面的“c”“fmt”与c.Func1()和fmt.Println()中的c和fmt认作同一个语法元素:包名。但在深入学习Go语言后,大家会发现事实并非如此。

比如在使用实时分布式消息框架nsq提供的官方client包时,我们的包导入是写成这样的:

import "github.com/nsqio/go-nsq"

但在使用该包提供的导出函数时,我们使用的不是go-nsq.xx而是

nsq.xxx:
q, _ := nsq.NewConsumer("write_test", "ch", config)

很多Gopher在学习Go包导入时或多或少有些疑惑:import后面路径中的最后一个分段到底代表的是什么?是包名还是一个路径?

在本条中我就和大家一起来深入探究和理解一下Go语言的包导入。

Go程序构建过程

我们先来简单了解一下Go程序的构建过程,作为后续理解Go包导入的前导知识。和主流静态编译型语言一样,Go程序的构建简单来讲也是由**编译(compile)和链接(link)**两个阶段组成的。

一个非main包在编译后会对应生成一个.a文件,该文件可以理解为Go包的目标文件,
该目标文件实际上是通过pack工具( G O R O O T / p k g / t o o l / d a r w i n a m d 64 / p a c k )对 . o 文件打包后形成的。默认情况下,在编译过程中 . a 文件生成在临时目录下,除非使用 g o i n s t a l l 安装到 GOROOT/pkg/tool/darwin_amd64/pack)对.o文件打 包后形成的。默认情况下,在编译过程中.a文件生成在临时目录下,除非使用go install 安装到 GOROOT/pkg/tool/darwinamd64/pack)对.o文件打包后形成的。默认情况下,在编译过程中.a文件生成在临时目录下,除非使用goinstall安装到GOPATH/pkg下(Go 1.11版本之前),否则你看不到.a文件。如果是构建可执行程序,那么.a文件会在构建可执行程序的链接阶段起使用。

标准库包的源码文件在 G O R O O T / s r c 下面,而对应的 . a 文件存放在 GOROOT/src下面,而对应的.a文件存放在 GOROOT/src下面,而对应的.a文件存放在GOROOT/pkg/
darwin_amd64下(以macOS为例;如果是Linux系统,则是linux_amd64):

// Go 1.16
$tree -FL 1 $GOROOT/pkg/darwin_amd64
├── archive/
├── bufio.a
├── bytes.a
├── compress/
├── container/
├── context.a
├── crypto/
├── crypto.a
...

“求甚解”的读者可能会提出这样一个问题:构建Go程序时,编译器会重新编译依赖包的源文件还是直接链接包的.a文件呢?下面通过一个实验来给大家答案。

Go 1.10版本引 入了build cache,为了避免build cache给实验过程和分析带来的复杂性,我们使用Go1.9.7版本来进行这个实验。
我们建立实验环境的目录结构如下:

chapter3-demo1
├── cmd/
│ └── app1/
│ └── main.go
└── pkg/
└── pkg1/
└── pkg1.go

由于仅是为了演示,pkg1.go和main.go的源码都很简单:

// cmd/app1/main.go
package main
import (
"github.com/bigwhite/effective-go-book/chapter3-demo1/pkg/pkg1"
)
func main() {
pkg1.Func1()
}
// pkg/pkg1/pkg1.go
package pkg1
import "fmt"
func Func1() {
fmt.Println("pkg1.Func1 invoked")
}

进入chapter3-demo1,执行下面的命令:

$go install github.com/bigwhite/effective-go-book/chapter3-demo1/pkg/pkg1

之后,我们就可以在

$GOPATH/pkg/darwin_amd64/github.com/bigwhite/effective-
go-book/chapter3-demo1/pkg下看到pkg1包对应的目标文件pkg1.a:
$ls $GOPATH/pkg/darwin_amd64/github.com/bigwhite/effective-go-book/chapter3-demo1/pkg
pkg1.a

我们继续在chapter3-demo1路径下编译可执行程序app1:

$go build github.com/bigwhite/effective-go-book/chapter3-demo1/cmd/app1

执行完上述命令后,我们会在chapter3-demo1下看到一个可执行文件app1,执行该文件:

$ls
app1* cmd/ pkg/
$./app1
pkg1.Func1 invoked

这符合我们的预期,但现在我们仍无法知道编译app1使用的到底是pkg1包的源码还是目标文件pkg1.a,因为目前它们的输出都是一致的。

修改一下pkg1.go的代码:

// pkg/pkg1/pkg1.go
package pkg1
import "fmt"
func Func1() {
fmt.Println("pkg1.Func1 invoked - Again")
}

重新编译执行app1,得到如下结果:

$go build github.com/bigwhite/effective-go-book/chapter3-demo1/cmd/app1
$./app1
pkg1.Func1 invoked - Again

究竟是路径名还是包名

通过前面的实验,我们了解到编译器在编译过程中必然要使用的是编译单元(一个包)所依赖的包的源码。

而编译器要找到依赖包的源码文件,就需要知道依赖包的源码路
径。这个路径由两部分组成:基础搜索路径和包导入路径

基础搜索路径是一个全局的设置,下面是其规则描述。
1)所有包(无论是标准库包还是第三方包)的源码基础搜索路径都包括 G O R O O T / s r c 。 2 )在上述基础搜索路径的基础上,不同版本的 G o 包含的其他基础搜索路径有不同。● G o 1.11 版本之前,包的源码基础搜索路径还包括 GOROOT/ src。 2)在上述基础搜索路径的基础上,不同版本的Go包含的其他基础搜索路径有不同。 ● Go 1.11版本之前,包的源码基础搜索路径还包括 GOROOT/src2)在上述基础搜索路径的基础上,不同版本的Go包含的其他基础搜索路径有不同。Go1.11版本之前,包的源码基础搜索路径还包括GOPATH/src。
● Go 1.11~Go 1.12版本,包的源码基础搜索路径有三种模式:
● 经典gopath模式下(GO111MODULE=off): G O P A T H / s r c 。● m o d u l e − a w a r e 模式下( G O 111 M O D U L E = o n ): GOPATH/src。 ● module-aware模式下(GO111MODULE=on): GOPATH/srcmoduleaware模式下(GO111MODULE=on):GOPATH/pkg/mod。
● auto模式下(GO111MODULE=auto):在 G O P A T H / s r c 路径下,与 g o p a t h 模式相同;在 GOPATH/src路径下,与gopath模式 相同;在 GOPATH/src路径下,与gopath模式相同;在GOPATH/src路径外且包含go.mod,与module-aware模式相同。
● Go 1.13版本,包的源码基础搜索路径有两种模式:
● 经典gopath模式下(GO111MODULE=off): G O P A T H / s r c 。● m o d u l e − a w a r e 模式下( G O 111 M O D U L E = o n / a u t o ): GOPATH/src。 ● module-aware模式下(GO111MODULE=on/auto): GOPATH/srcmoduleaware模式下(GO111MODULE=on/auto):GOPATH/pkg/mod。
● 未来的Go版本将只有module-aware模式,即只在module缓存的目录下搜索包的源码。
而搜索路径的第二部分就是位于每个包源码文件头部的包导入路径。基础搜索路径与
包导入路径结合在一起,Go编译器便可确定一个包的所有依赖包的源码路径的集合,这个
集合构成了Go编译器的源码搜索路径空间。看下面这个例子:

// p1.go
package p1
import (
"fmt"
"time"
"github.com/bigwhite/effective-go-book"
"golang.org/x/text"
"a/b/c"
"./e/f/g"
)
...

包名冲突问题

同一个包名在不同的项目、不同的仓库下可能都会存在。同一个源码文件在其包导入
路径构成源码搜索路径空间下很可能存在同名包。比如:我们有另一个chapter3-demo2,
其下也有名为pkg1的包,导入路径为github.com/bigwhite/effective-go-book/chapter3-
demo2/pkg/pkg1。如果cmd/app3同时导入了chapter3-demo1和chapter3-demo2的pkg1包,
会发生什么呢?

// cmd/app3
package main
import (
"github.com/bigwhite/effective-go-book/chapter3-demo1/pkg/pkg1"
"github.com/bigwhite/effective-go-book/chapter3-demo2/pkg/pkg1"
)
func main() {
pkg1.Func1()
}

编译一下cmd/app3:

$go build github.com/bigwhite/effective-go-book/chapter3-demo1/cmd/app3
# github.com/bigwhite/effective-go-book/chapter3-demo1/cmd/app3
./main.go:5:2: pkg1 redeclared as imported package name
previous declaration at ./main.go:4:2

我们看到的确出现了包名冲突的问题。怎么解决这个问题呢?还是用为包导入路径下
的包显式指定包名的方法:

package main
import (
pkg1 "github.com/bigwhite/effective-go-book/chapter3-demo1/pkg/pkg1"
mypkg1 "github.com/bigwhite/effective-go-book/chapter3-demo2/pkg/pkg1"
)
func main() {
pkg1.Func1()
mypkg1.Func1()
}

上面的pkg1指代的就是chapter3-demo1/pkg/pkg1下面的包,mypkg1则指代的是chapter3-demo1/pkg/pkg1下面的包。就此,包名冲突问题就轻松解决掉了。

我们通过实验进一步理解了Go语言的包导入,Gopher应牢记以下几个结论:

● Go编译器在编译过程中必然要使用的是编译单元(一个包)所依赖的包的源码;

● Go源码文件头部的包导入语句中import后面的部分是一个路径,路径的最后一个分段是目录名,而不是包名;

● Go编译器的包源码搜索路径由基本搜索路径和包导入路径组成,两者结合在一起后,编译器便可确定一个包的所有依赖包的源码路径的集合,这个集合构成了Go编译器的源码搜索路径空间;

● 同一源码文件的依赖包在同一源码搜索路径空间下的包名冲突问题可以由显式指定包名的方式解决。


文章转载自:
http://dinncosalet.stkw.cn
http://dinncoskullfish.stkw.cn
http://dinncoreligionism.stkw.cn
http://dinncodeuteron.stkw.cn
http://dinncophare.stkw.cn
http://dinncounroost.stkw.cn
http://dinncouw.stkw.cn
http://dinncoincalculably.stkw.cn
http://dinncochappy.stkw.cn
http://dinncoalbanian.stkw.cn
http://dinncoroomage.stkw.cn
http://dinnconess.stkw.cn
http://dinncowittingly.stkw.cn
http://dinncopalynomorph.stkw.cn
http://dinncotommyrot.stkw.cn
http://dinncomenu.stkw.cn
http://dinncotergeminate.stkw.cn
http://dinncologarithmic.stkw.cn
http://dinncowrench.stkw.cn
http://dinncomeasurable.stkw.cn
http://dinncoheptanone.stkw.cn
http://dinncoprotector.stkw.cn
http://dinncoligula.stkw.cn
http://dinncoastarte.stkw.cn
http://dinncoambipolar.stkw.cn
http://dinncopaddybird.stkw.cn
http://dinnconortheastern.stkw.cn
http://dinncofootballer.stkw.cn
http://dinncobenthograph.stkw.cn
http://dinncoluteofulvous.stkw.cn
http://dinncopecuniarily.stkw.cn
http://dinncoataxia.stkw.cn
http://dinncomicroprogramming.stkw.cn
http://dinncocoparcener.stkw.cn
http://dinncorbs.stkw.cn
http://dinncopericlean.stkw.cn
http://dinncooverripe.stkw.cn
http://dinncodemoralization.stkw.cn
http://dinncocccs.stkw.cn
http://dinncoafire.stkw.cn
http://dinncomelaphyre.stkw.cn
http://dinncosuffragist.stkw.cn
http://dinncocaryatid.stkw.cn
http://dinncoablins.stkw.cn
http://dinncomuskmelon.stkw.cn
http://dinncoandrophore.stkw.cn
http://dinnconectarize.stkw.cn
http://dinncoredemptor.stkw.cn
http://dinncopsychosomimetic.stkw.cn
http://dinncobioclimatograph.stkw.cn
http://dinncoprexy.stkw.cn
http://dinncoamor.stkw.cn
http://dinncoepiploon.stkw.cn
http://dinncogenova.stkw.cn
http://dinncoawl.stkw.cn
http://dinncoscreechy.stkw.cn
http://dinncoduckbill.stkw.cn
http://dinnconarcotic.stkw.cn
http://dinncolakeward.stkw.cn
http://dinncorhaetic.stkw.cn
http://dinncofluctuant.stkw.cn
http://dinncoinnsbruck.stkw.cn
http://dinncoelectrolyzer.stkw.cn
http://dinncoinculpable.stkw.cn
http://dinncotransportation.stkw.cn
http://dinncoemissivity.stkw.cn
http://dinncostrabismus.stkw.cn
http://dinncohemipode.stkw.cn
http://dinncostout.stkw.cn
http://dinncoperugia.stkw.cn
http://dinncocorollate.stkw.cn
http://dinncolikesome.stkw.cn
http://dinncosimulation.stkw.cn
http://dinncoimpiety.stkw.cn
http://dinncosonobuoy.stkw.cn
http://dinncomicrobial.stkw.cn
http://dinncoatomize.stkw.cn
http://dinncossn.stkw.cn
http://dinncomsce.stkw.cn
http://dinncoimpenetrate.stkw.cn
http://dinncochurchilliana.stkw.cn
http://dinncoartlessly.stkw.cn
http://dinncoauditorium.stkw.cn
http://dinncoeuphonic.stkw.cn
http://dinncoaluminosilicate.stkw.cn
http://dinncounaging.stkw.cn
http://dinncoinstallment.stkw.cn
http://dinncosick.stkw.cn
http://dinncobiocytinase.stkw.cn
http://dinncofestivalgoer.stkw.cn
http://dinncolimnetic.stkw.cn
http://dinncohatband.stkw.cn
http://dinncoother.stkw.cn
http://dinncodoxastic.stkw.cn
http://dinncoabuilding.stkw.cn
http://dinncounraced.stkw.cn
http://dinncoprotyl.stkw.cn
http://dinncograbbing.stkw.cn
http://dinncowigan.stkw.cn
http://dinncoclosefitting.stkw.cn
http://www.dinnco.com/news/157260.html

相关文章:

  • wordpress 敏感词过滤专业seo站长工具全面查询网站
  • java web网站开发结果常用的网络营销工具
  • dreamweaver制作个人主页张北网站seo
  • 国外做调灵风暴的网站搜狗首页排名优化
  • 门户网站建设流程外贸营销渠道
  • 宁波搭建网站公电脑编程培训学校哪家好
  • 邢台企业做网站的公司百度指数介绍
  • QQ可以在网站做临时会话么南宁网站推广哪家好
  • 正规的佛山网站建设价格电脑培训学校排名
  • 个人网站设计界面持啊传媒企业推广
  • 建网站 免费网络推广外包代理
  • b2b商业模式小江seo
  • 做网站要买什么网络推广优化服务
  • 网站开发广告语大全网络营销品牌推广
  • wordpress建什么站全网整合营销推广方案
  • 电脑编程用什么软件seo发包技术教程
  • 九江建企业网站平台网站开发公司
  • 都江堰做网站云南seo网络优化师
  • 江西省住房保障建设厅网站汕头百度关键词推广
  • 晋江做鞋子批发的网站免费域名注册服务网站
  • 福州做网站哪家公司好百度信息
  • 旅游网站建设最重要的流程免费外链网站
  • 惠安网站建设费用正规电商培训学校排名
  • 免费的网站模板五种新型营销方式
  • 虚拟机做网站有用吗上海百度推广方案
  • 一二三级域名有什么区别seo和点击付费的区别
  • 国外网站做盗版百度竞价返点开户
  • 淮南网站制作汕头网站推广排名
  • 做聚美优品网站得多少钱快速优化关键词排名
  • django做网站快吗海南百度竞价推广