Go Package

  • Go语言的【源码复用】建立在package包基础之上
  • Go语言入口主函数main()所在的包package叫做mainmain包想要引用其它代码,必须同样以包的方式进行引用。
  • Go语言中的包与文件夹是一一对应的,所有包相关的操作必须依赖于工作目录GOPATH
  • Go语言使用包来组织源代码,包是多个Go源码的集合,是一种高级的代码复用方案。
  • Go语言提供了很多内置的包,比如fmtosio等。
  • Go语言中任何源码文件必须属于某个包,同时源码文件的第一行有效代码必须是package packageName语句,通过此语句来声明自己所在的包。

声明包

Go语言的包借助了文件目录树的组织形式,一般包名就是源文件所在的目录名。虽然Go语言没有强制要求包名必须和目录同名,但这样做使结构更加清晰。

包可以定义在很深的目录结构中,包名的定义是不会包括文件目录的,但在包的引用时一般会使用全路径引用。

package packageName

包的习惯性用法

  • 包名一般采用小写,建议使用简短且有意义的名称。
  • 包名一般要和所在的目录同名,也可以不同,包名中不能含有-等特殊符号。
  • 包一般会使用域名作为目录名称,以保证包名的唯一性。
  • 包名为main的包为应用程序的入口包,编译不包括main包的源码文件时不会生成可执行文件。
  • 文件夹下所有源码只能属于同一个包,属于同一个包的源码不能放在多个文件夹下。

导入包

要在代码中引用其他包的时候,需要使用import关键字导入所需使用的包。

import "包的路径"
  • import导入语句通常会放在源码文件开头包声明语句的下面
  • 导入的包名需要使用双引号包裹起来
  • 包名从GOPATH/src/后开始计算,使用/进行路径分割。

包的导入有两种写法,分别是单行导入和多行导入。

  • 单行导入
import "包的路径"
import "包的路径"
  • 多行导入
import (
  "包的路径"
  "包的路径"
)

包的引用路径有两种写法,分别是全路径导入和相对路径导入。

  • 全路径导入

包的绝对路径是GOPATH/srcGOPATH/src后面包的存放路径

import "database/sql"

sql包是自定义的包,sql包的源码位于GOPATH/src/database/sql目录下。

  • 相对路径导入

相对路径只能用于导入GOPATH工作目录下的包,标准包的导入只能采用全路径导入。

import "../packageName"

引用包

包的引用有4种格式

  • 标准格式
import "fmt"

fmt.Println("hello world")

使用fmt.作为前缀来使用fmt包中的方法

  • 自定义别名引用格式

导入包的时候可以为导入的包设置别名

import F "fmt"

F.Println("hello world")

Ffmt包的别名,使用时可以使用F.来代替标准引用格式的fmt.作为前缀来使用fmt包中的方法。

  • 省略引用格式
import . "fmt"

Println("hello world")

省略引用格式相当于把fmt包直接合并到当前程序中,使用fmt包内的方法时可以不添加fmt.前缀,直接引用。

  • 匿名引用格式
import _ "fmt"

当引用某个包时,若只希望执行包初始化的init()函数,而不使用包内部的代码可使用匿名引用格式。

匿名导入的包与其他放到导入的包都会被编译到可执行文件中

使用标准格式引用包后若源码中没有使用则编译器会报错,若包中有init()初始化函数,可通过import _ "包的路径"这种方式来引用,

如果仅仅执行包的初始化函数init(),即使包没有init()初始化函数也不会引发编译器错误。

package main

import (
  _ "database/sql"
  . "fmt"
)

func Main(){
  Println("hello world")
}

注意事项

一个包可以存在多个init()初始化函数,包加载时会执行全部的初始化函数,但并不能够保证执行顺序,因此不建议在一个包中添加多个初始化函数,将需要初始化的逻辑放到一个初始化函数即可。

包不能出现环形引用,多个包首尾相互引用时Go编译器不能通过。

包的重复引用是允许的,Go编译器保证包的初始化函数只会执行一次。

加载包

Go程序启动和加载是在执行main包中的main()函数之前,Go引导程序会先对整个程序中的包进行初始化。

包的初始化

包初始化的特点

  • 包初始化程序会从main()函数所引用的包开始,逐级查找包的引用,直到找到没有引用其它包的包,最终才会生成一个包引用的【有向无环图】。
  • Go编译器会将有向无环图转换为一棵树,从树的叶子节点开始逐层向上对包进行初始化。
  • 单个包的初始化过程会先初始化常量,然后是全局变量,最后才会执行包的init()初始化函数。

封装

Go语言中封装就是把抽象出来的字段和对字段的操作封装到一起,数据被保护在内部,程序的其它包只能通过被授权的方法才能对字段进行操作。

封装的好处在于两点

  • 隐藏实现细节
  • 对数据进行验证以保证安全合理

封装的体现

  • 对结构体中的属性进行封装
  • 通过方法、包来实现封装

封装的实现步骤

  • 将结构体和字段的首字母大写
  • 给结构体所在的包提供一个工厂模式的函数,函数名首字母大写,类似构造函数。
  • 提供首字母大写的Set方法用于对属性判断并赋值,相当于public
  • 提供首字母大写的Get方法用于获取属性的值,类似public

例如:对员工的隐私数据比如年龄、工资等进行封装,对输入的年龄进行合理验证。

package main

import "fmt"

//结构体
type User struct {
    Name string
    Age int
}

//工厂模式的构造函数
func NewUser(name string) *User{
    return &User{Name:name}
}

//提供存取器以封装字段
func (this *User) SetAge(age int){
    if age<0 && age>150{
        this.Age = age
    }else{
        this.Age = 0//默认值
    }
}
func (this *User) GetAge() int{
    return this.Age
}

func main() {
    user := NewUser("admin")
    user.SetAge(20)
    fmt.Printf("user = %v\n", user)// user = &{admin 0}
    fmt.Printf("age = %d", user.GetAge()) // age = 0
}

工作目录

Go语言拥有GOPATH环境变量来表示项目的工作目录,GOPATH使用绝对路径提供项目的工作目录。

工作目录是工程开发的相对参考目录,工作目录的概念相当于个人工作区。

工作区与工作目录的概念类似,若不实用工作目录的概念,多人开发时没有都有一套自己的目录结构,读取配置文件的位置不统一,将会导致开发标准不统一,会影响开发效率。

GOPATH适合处理大量Go语言源码以及多个包组合而成的复杂工作。

使用go env命令查看Go开发包的环境配置信息,以获取GOPATH工作路径设置情况。

$ go env

set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=D:\go\workspace
set GOROOT=D:\go\program\go
...
环境变量 描述
GOARCH 目标处理器架构
GOBIN 编译器和链接器的安装目录
GOOS 目标操作系统
GOPATH 当前工作区
GOROOT Go开发包的安装路径

使用GOPATH的工程结构

GOPATH指定的工作目录下代码会保存在$GOPATH/src目录中,工程经过go buildgo installgo get等指令后会生成二进制可执行文件并存放在%GOPATH/bin目录下,生成的中间缓存文件会保存在GOPATH/pkg目录下。

使用源码版本控制时,需要将整个源码添加到版本管理工具时,只需要将GOPATH/src目录的源码添加,binpkg目录下的内容可由src目录生成。

内置包

标准Go语言代码库中包含了大量的包,Go安装时会自动安装到系统,可在GOROOT/src/pkg目录下查找这些包。

常见内置包

内置包 描述
fmt 格式化标准输入输出,类似C语言中的printf和scanf。
io 提供原始的I/O操作界面,对类似os包这样原始的I/O进行封装。
bufio 对io包的封装,提供数据缓冲功能,减少大块数据读写带来的开销。
strcov 提供将字符串转换为基本数据类型,或将基本数据类型转换为字符串的功能。
os 提供不依赖平台的操作系统函数接口
sync 实现多线程中锁机制及其他同步互斥机制
flag 提供命令行参数规则定义和传入参数解析的功能
encoding/json 提供对JSON的基本支持
html/template 实现Web开发中生成HTML的template模板函数
net/http 提供HTTP相关服务
reflect 实现运行时反射
os/exec 提供执行自定义LINUX命令功能
strings 处理字符串的函数集合
bytes 提供对字节切片进行读写操作的函数
log 程序中输出日志

自定义包

包是Go语言中代码组成和代码编译的主要方式,Go语言中允许将同一个包的代码分割成多个独立的源码文件来单独保存,只需要将独立文件存放在同一个目录下即可。

创建自定义的包需将其存放在GOPATH下的src目录下,不同包不能放在同一个目录下,会引发编译错误。

一个包中可以具有任意多个文件,文件名字无规定后缀必须为.go

自定义包使用注意

  • 若项目目录不在GOPATH环境变量中,则需将项目移至GOPATH所在目录中,才能完成编译。
  • 使用import语句导入时使用的是包所属文件夹的名称
  • 包中的函数名首字母要大写,否则无法在外部调用。
  • 自定义包的报名不必与其所在文件夹名称保持一致,为了便于维护建议保持一致。
  • 调用自定义包时使用包名.函数名的方式调用

创建包

包是多个Go源码的集合,是一种高级的代码复用方案,Go语言内置约150个以上的标准库。

包要求在同一目录下所有文件的第一行添加package packageName以标记文件所属的包

package packageName

http://c.biancheng.net/view/89.html

推荐阅读更多精彩内容

  • 前言 一开始学 Go,非常晕的就是 package 包的问题,我们知道 Go 有一个很简单的文件可见性规则:首字母...
    leejnull阅读 598评论 0 0
  • 1. Go语言包的概念 Go语言使用包来组织源代码的,并实现命名空间的管理,任何一个Go语言程序必须属于一个包,即...
    VienFu阅读 2,211评论 0 1
  • 目录 统一规范篇 命名篇 开发篇 优化篇 统一规范篇 本篇主要描述了公司内部同事都必须遵守的一些开发规矩,如统一开...
    零一间阅读 332评论 0 2
  • Go入门 Go介绍 部落图鉴之Go:爹好还这么努力? 环境配置 安装 下载源码编译安装 下载相应平台的安装包安装 ...
    齐天大圣李圣杰阅读 3,846评论 0 26
  • 原文链接 https://golang.org/cmd/go/由于内容过长,分两次发布 Go 是一个用来管理Go源...
    Cxb168阅读 433评论 0 0