go package包的使用以及路径问题

前言

一开始学 Go,非常晕的就是 package 包的问题,我们知道 Go 有一个很简单的文件可见性规则:首字母大写即对外可见,但是不知道对外是对什么外。
以及我在一个 ch1 目录下,创建一个 demo.go 文件,在输入 package 时, VS 又会自动提示 package ch1,这个和 main 又有什么关系呢?
我在一个 ch1 目录下写了一个 demo.go 文件,里面有一个函数,我在 ch2/demo2.go 里面想用又该怎么 import 呢?
带着这些疑问,这次来系统的了解一下~

Go的环境变量

在我们安装完 go 之后,输入

go env

会输出一大堆信息,其中 GOPATH 就是我们的工作区,我们写了一个 demo.go 文件,其中如果 import 了一些第三方库,运行的时候就会先从 GOROOT 中找,如果没有找到会再去 GOPATH 里面找
我们可以通过修改 GOPATH 添加额外的工作区,在你的 .zshrc / .bash_profile 文件里面

export GOPATH="/Users/lijun/go:/Users/lijun/Documents/Go/golearning"

引入第三方库

一般我们通过

go get -u github.com/julienschmidt/httprouter

这个指令下载的第三方库都会保存在 GOPATH 第一个工作区指定的 src 目录下
只需要在项目里

import "github.com/julienschmidt/httprouter"

就能使用这个第三方包了

有时候 go get 下载失败,可以手动去 GitHub 下载源代码,放到对应目录下,记住路径要和 GitHub 上的文件路径一致

在当前文件使用另一个文件定义的函数或变量

  • 同级目录
    在class文件夹下新建 demo.go 和 demo_lib.go
// demo_lib.go
package main

import "fmt"

func hello(name string) {
    fmt.Printf("Hello, %s!\n", name)
}
// demo.go
package main

import "flag"

var name string

func init() {
    flag.StringVar(&name, "name", "everyone", "The greeting object.")
}

func main() {
    flag.Parse()
    hello(name)
}

当在一个同级目录下面,有一个 package main 实现了 main() 函数的时候,这是作为程序的唯一入口。在同级目录下,别的文件也必须 package main,且不能再实现 main() 函数,否则提示 redeclared 错误。
此时 demo_lib.go 文件里的变量和函数对 demo.go 都是可见的。且不受可见性影响

  • 不同级目录
    现在我们在 class 文件夹下新建 lib 文件夹,在新建一个 demo2_lib.go 文件,demo2_lib 现在就有两种可能了
    1. package main 并且实现 main() 函数,那么它就是另一个新程序的入口了,内部的函数和变量就不能被别的文件 import
    2. package 包名,这样的话是可以被外部使用,但是我们需要把首字母大写,对外部可见(这里了解了对外部是指对别的包而言),我们现在测试这种情况
package lib

import "fmt"

func Hello(name string) {
    fmt.Println("Hello, %s!\n",)
}

如果 demo.go 要使用 demo2_lib 下的 Hello 函数,需要导入这个包。这时候我们需要 go install 一下

go install class/lib

后面的路径是要导入的包的相对路径,执行完之后,会在我们的工作区下生成 pkg/darwin_amd64/class/lib.a


2019-08-21-11.png

在 demo.go 导入即可

package main

import (
    "class/lib"
    "flag"
)

var name string

func init() {
    flag.StringVar(&name, "name", "everyone", "The greeting object.")
}

func main() {
    flag.Parse()
    lib.Hello(name)
}

到这里我们算是完成了一个供外部调用的包的程序

这里有个疑问

我在 class/lib 文件夹下创建的 demo2_lib.go 文件,并且 package lib,package的包名和所在文件夹名有必然联系吗?

// demo2_lib.go
package lib2

import "fmt"

func Hello(name string) {
    fmt.Printf("Hello, %s!\n", name)
}

改成 lib2 试一下
go install 后面跟的是路径,所以依然是 class/lib

go install class/lib

在主函数什么都不改变,调用

go run demo.go

此时提示

# command-line-arguments
./demo.go:4:2: imported and not used: "class2/lib" as lib2
./demo.go:18:2: undefined: lib

从字面上理解一下的话,第一个是说导入了但是没有把 class2/lib 当做 lib2 来使用,第二行说没有定义的 lib

emmm~~~

我记得 import 包的时候可以起个别名的,试一下

package main

import (
    lib2 "class/lib"
    "flag"
)

var name string

func init() {
    flag.StringVar(&name, "name", "everyone", "The greeting object.")
}

func main() {
    flag.Parse()
    lib2.Hello(name)
}

继续运行一下,输出结果

lijun:class2/ $ go run demo.go     
Hello, everyone!

可以了!!!
想一下,我们主要做了什么,和之前有什么不同
在路径 class/lib 下,demo2_lib.go 文件没有 package lib,而是 package lib2

// 原来
package lib

// 现在
package lib2

go install class/lib 这个步骤没有变也变不了。
最后在 main 函数中调用,原来是

import "class/lib"

lib.Hello(name)

现在是

import lib2 "class/lib"

lib2.Hello(name)

也就是说,当我们要在一个项目里新建一个 tool 文件夹放我们的工具包,我们可以不 package tool,而是可以写一个别的包名,依然可以使用,只不过在使用的时候,import 的还是 pkg 下的路径,但是要给这个 import 设置它真正的包名,即这里的 lib2

总结

算是弄明白了 Go 下的文件引用,以及 GOPATH 的设置。
同一级目录下只能有一个 main,且别的文件对它都是可见的,不需要设置大小写都可以被访问到,不同级目录,根据首字母大小写可见,还需要 go install一下,再 import 对应路径,包名可以和路径不一致,但是要设置别名。
简单了解后,如果还有别的疑惑欢迎大家一起探讨!

来自 https://leejnull.github.io/2019/08/21/2019-08-21-1/

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容

  • 本项课程分为两个阶段,第一阶段将让学员全面了解并掌握Hadoop的架构原理和使用场景,并通过贯穿课程的项目进行实战...
    小波yagamis阅读 392评论 0 1
  • 不知不觉我要混成了适龄结婚女青年,周围人纷纷踏入婚姻的围城,而我在围城之外自得其乐。 嗯,接下来要讲故事了,...
    胖胖欢阅读 377评论 0 0
  • 关于爱你 清晨,阳光开始温暖,像隔壁阿姨家厨房里的饭菜香味,让人想念。这是一个美丽的清晨,可以让人忘掉忧伤。 每个...
    磊平阅读 313评论 0 2