go包的理解
结论:
- import时指定的字符串,是相对于$GOPATH的目录路径,告诉了go,要去加载这个目录下所有的包文件(不包括子目录中的文件)
- 一个目录中所有的源文件(不包括子目录)代表了单独的一个包,这些源文件内的package关键字指出的包名,必须一致,否则无法被使用
- import指定的加载目录、目录中的源文件名字、源文件内通过package关键字指定的包名。这三者可以不一样。导入后,根据package指定的包名,来使用包中的导出成员。
- 导入两个目录,这两个目录中的源文件内指定的包名,如果出现相同,则导入目录时会失败
- 同一个包,间接或直接被导入多次。这个包只会被初始化一次。如init执行一次,包级别变量的内存只会被分配一次,后续要使用的话,则继续使用上次分配时的值。(这个规律和nodejs也是一致的)这也就是为什么使用mysql时,要导入两个包:
import "database/sql"
import _ "github.com/go-sql-driver/mysql"-
第二个包中引用了第一个包,init函数中对第一个包里的数据进行了一些mysql相关的操作。使后续直接使用第一个包时,能关联得上mysql。
- 导入第二个包仅仅是为了执行里面的init函数,从而影响第一个包的行为。所以第二个包空导入即可
- 当源文件被加载时,文件内的init函数会被自动执行:
- 通过import来加载一个目录时,如果这个目录中有多个源文件,则这些源文件中的init函数都会执行,但文件之间的init函数的执行次序不确定,看go加载文件是的顺序
- 一个源文件内可以定义多个init函数,多个init函数会按顺序从上往下执行。虽然一个文件内可以定义多个init,但是没有这个必要,把逻辑都集中在一个init函数中,效果一样
测试1
$GOPATH目录如下:
├─pkg
└─src
└─app.go
└─m1
└─k1.go
app.go:
package main import "m1" func main() {
x1.Show()
}
k1.go:
package x1 import "fmt" func Show(){
fmt.Println("show call")
}
运行app.go:输出 show call。
测试2
在以上的m1目录中,创建一个文件k2.go
package x2 import "fmt" func Show(){
fmt.Println("show call")
}
运行app.go提示:app.go:3:8: found packages x1 (k1.go) and x2 (k2.go) in D:\GoPath\src\m1
测试3
k1和k2文件中,都通过package指定包名为x1。app.go中导入这两个目录,运行报错:
.\app.go:4:8: x1 redeclared as imported package name
previous declaration at .\app.go:3:8
.\app.go:7:2: undefined: "m2".FnInK1
解决办法:导入的时候,将冲突的包名,重命名为另一个值即可,如以下k2pkg
测试4
k1.go:
package x1 import "fmt" var x1Data int = ; func init(){
fmt.Println("x1 init call")
x1Data = ;
} func ShowData(){
fmt.Println(x1Data)
} func SetData(x int){
x1Data = x;
}
k2.go:
package x2 import "m1"
import "fmt" func init(){
fmt.Println("x2 init call")
x1.SetData()
}
app.go:
package main import _ "m2"
import "m1" func main() {
x1.ShowData()
}
> go run app.go
x1 init call
x2 init call
333
go包的理解的更多相关文章
- socket模块粘包现象理解以及解决思路
粘包现象: 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发两端(客户端和服务器端)都要有成对的socket,因此,发送端为了将多个发往接收端的 ...
- JavaScript-闭包函数(理解)
JavaScript-闭包函数(理解) var foo = function (a) { return function inner () { console.log(a) } } var faa = ...
- GDT,LDT,GDTR,LDTR 详解,包你理解透彻(转)
引自:http://www.techbulo.com/708.html 一.引入 保护模式下的段寄存器 由 16位的选择器 与 64位的段描述符寄存器 构成 段描述符寄存器: 存储段描述符 选择器:存 ...
- js--闭包的理解
从技术上来讲,在JS中,每个function都是闭包,因为它总是能访问在它外部定义的数据. 当该内部函数在外部函数外被调用,就生成了闭包. 函数内部可以直接读取全局变量. 闭包就是能够读取其他函数内部 ...
- (linux)BSP板级支持包开发理解
1. 概述 嵌入式系统由硬件环境.嵌入式操作系统和应用程序组成,硬件环境是操作系统和应用程序运行的硬件平台,它随应用的不同而有不同的要求.硬件平台的多样性是嵌入式系统的主要特点,如何使嵌入式操作系统在 ...
- 导入项目后下载jar包问题理解
1.导入,然后你下载的jar包,jar下载成功,并不代表你项目里的代码就能用这个jar包了. 你必须还要本地添加进classpath.必须手动添加进类路径 2.总结就是:下载jar包是下载jar包,添 ...
- Java 包的理解与使用
java中的包可以分为两种:内置包.用户自己定义的包.这里介绍的是用户自定义的包. 一.包的使用 1.创建PackageTest.java package com.packtest; public c ...
- 深入探讨 java.lang.ref 包
深入探讨 java.lang.ref 包 本文主要探讨了 java.lang.ref 包的使用方法,以及源码解读.并就该包在不同 JVM 上的表现进行了比较与分析.通过阅读本文,读者可以加深对 jav ...
- tcpdump抓包命令
本文转自 : http://www.cnblogs.com/ggjucheng/archive/2012/01/14/2322659.html http://www.itshouce.com.cn/l ...
随机推荐
- 自动生成actionbar 所需图片和style
http://jgilfelt.github.io/android-actionbarstylegenerator/
- Ashx增删改查_动软
1.首先展示列表 ashx 讲究的是个替换 这些就是属于ashx麻烦的地方 public void ProcessRequest(HttpContext context) { context.Resp ...
- Get和Post的请求
get post请求 <form method="post","get", action="a.ashx"> <input ...
- mysq表的三种关系,数据的增删改以及单表多表查询
一丶三种关系 分析步骤: #.先站在左表的角度去找 是否左表的多条记录可以对应右表的一条记录,如果是,则证明左表的一个字段foreign key 右表一个字段(通常是id) #.再站在右表的角度去找 ...
- Bootstrap插件-collapse
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title> ...
- 设置mapcontrol的鼠标样式
http://blog.itpub.net/14999074/viewspace-586515/ mapcontrol的鼠标样式 this.axMapControl1.MousePointer=esr ...
- fstab 解析
某些时候当Linux系统下划分了新的分区后,需要将这些分区设置为开机自动挂载,否则,Linux是无法使用新建的分区的. /etc/fstab 文件负责配置Linux开机时自动挂载的分区. Window ...
- Android学习笔记1——Android开发环境配置
一.JDK配置 Android是基于Java进行开发的,首先需要在电脑上配置JDK(Java Development Kit).在http://www.androiddevtools.cn/下载对应系 ...
- 大数四则运算java(转)
// 大数的四则运算 #include <iostream> #include <string> #include <algorithm> using namesp ...
- 解决windows7系统的快捷方式无法添加到任务栏
#以下4条,进入cmd命令界面下逐个执行cmd /k reg add "HKEY_CLASSES_ROOT\lnkfile" /v IsShortcut /fcmd /k reg ...