一、概述

  Golang拥有超过100个标准包(可用go list std |wc -l查看)

  任何包系统设计的目的都是简化大型程序的设计和维护工作,通过将一组相关的特性放进一个独立的模块以便于理解和更新,在每个模块更新的同时保持和程序中其他模块的相对独立,这种模块化的特性允许每个包能被其他的不同项目共享和重用,在项目范围内、全局范围内的复用;

  每个包一般都定义了一个不同的名字空间用于它内部的每个标识符的访问。 每个名字空间关联到一个特定的包, 让我们给类型、 函数等选择简短明了的名字, 这样可以避免在我们使用它们的时候减少和其它部分名字的冲突。

  每个包还通过控制包内名字的可见性和是否导出来实现封装特性。 通过限制包成员的可见性并隐藏包API的具体实现, 将允许包的维护者在不影响外部包用户的前提下调整包的内部实现。 通过限制包内变量的可见性, 还可以强制用户通过某些特定函数来访问和更新内部变量, 这样可以保证

内部变量的一致性和并发时的互斥约束。

二、包的使用之导入路径

  每个包是由一个全局唯一的字符串所标识的导入路径定位。 出现在import语句中的导入路径也是字符串。

import (
"fmt"
"math/rand"
"encoding/json"
"golang.org/x/net/html"
"github.com/go-sql-driver/mysql"
)

三、包声明:

  在每个Go源文件的开头都必须有包声明语句。 包声明语句的主要目的是确定当前包被其它包导入时默认的标识符(也称为包名)

  例如, math/rand包的每个源文件的开头都包含 package rand 包声明语句, 所以当你导入这个包, 你就可以用rand.Int、 rand.Float64类似的方式访问包的成员。

  关于默认包名一般采用导入路径名的最后一段的约定也有三种例外情况。

    第一个例外, 包对应一个可执行程序, 也就是main包, 这时候main包本身的导入路径是无关紧要的。 名字为main的包是给go build( §10.7.3) 构建命令一个信息, 这个包编译完之后必须调用连接器生成一个可执行程序。

    第二个例外, 包所在的目录中可能有一些文件名是以test.go为后缀的Go源文件( 译注:前面必须有其它的字符, 因为以``前缀的源文件是被忽略的) , 并且这些源文件声明的包名也是以_test为后缀名的。 这种目录可以包含两种包:一种普通包, 加一种则是测试的外部扩展包。

  所有以_test为后缀包名的测试外部扩展包都由go test命令独立编译, 普通包和测试的外部扩展包是相互独立的。 测试的外部扩展包一般用来避免测试代码中的循环导入依赖。

    第三个例外, 一些依赖版本号的管理工具会在导入路径后追加版本号信息, 例如"gopkg.in/yaml.v2"。 这种情况下包的名字并不包含版本号后缀, 而是yaml。  

   warning:如果我们想同时导入两个有着名字相同的包, 例如math/rand包和crypto/rand包, 那么导入声明必须至少为一个同名包指定一个新的包名以避免冲突。 这叫做导入包的重命名。

    import (
      "crypto/rand"
      mrand "math/rand"   // alternative name mrand avoids conflict
    )

  warning:匿名导入:

    import _ "image/png" // register PNG decoder

 // The jpeg command reads a PNG image from the standard input
// and writes it as a JPEG image to the standard output.
package main
import (
  "fmt"
  "image"
  "image/jpeg"
  _ "image/png" // register PNG decoder
  "io"
  "os"
)
func main() {
  if err := toJPEG(os.Stdin, os.Stdout); err != nil {
    fmt.Fprintf(os.Stderr, "jpeg: %v\n", err)
    os.Exit(1)
  }
}
func toJPEG(in io.Reader, out io.Writer) error {
  img, kind, err := image.Decode(in) //这里可能需要匿名导入
  if err != nil {
    return err
  }
  fmt.Fprintln(os.Stderr, "Input format =", kind)
  return jpeg.Encode(out, img, &jpeg.Options{Quality: 95})
}

  下面说说工作机制。 标准库还提供了GIF、 PNG和JPEG等格式图像的解码器,用户也可以提供自己的解码器, 但是为了保持程序体积较小, 很多解码器并没有被全部包含, 除非是明确需要支持的格式。 image.Decode函数在解码时会依次查询支持的格式列表。

  每个格式驱动列表的每个入口指定了四件事情:格式的名称;一个用于描述这种图像数据开头部分模式的字符串, 用于解码器检测识别;一个Decode函数用于完成解码图像工作;一个DecodeConfig函数用于解码图像的大小和颜色空间的信息。 每个驱动入口是通过调用image.RegisterFormat函数注册, 一般是在每个格式包的init初始化函数中调用, 例如image/png包是这样注册的:

 package png // image/png
func Decode(r io.Reader) (image.Image, error)
func DecodeConfig(r io.Reader) (image.Config, error)
func init() {
  const pngHeader = "\x89PNG\r\n\x1a\n"
  image.RegisterFormat("png", pngHeader, Decode, DecodeConfig)
}

  最终的效果是, 主程序只需要匿名导入特定图像驱动包就可以用image.Decode解码对应格式的图像!

四、自定义自己的包:

  包是函数和数据的集合。用 package 关键字定义一个包。文件名不需要与包名一致,但是你的文件夹必须要与包名字一致,这个很重要,所以为了简单起见,名字都是一样的。包名的约定是使用小写字符。Go 包可以由多个文件组成,但是使用相同的;
  package 这一行。让我们在文件 test1.go 中定义一个叫做 pkg的包。

 ├── pkg
│   └── myprint.go //myprint.go
package pkg
import "fmt"
func MyPrintf(in string) {
fmt.Printf("%s", in)
}

  在main包中测试:

 package main
import (
"fmt"
"./pkg" //带上路径
) func main() {
pkg.MyPrinf("my pkg test")
fmt.Printf("test ok")
} //测试ok
稍作修改:
package main
import (
"fmt"
"pkg" //不带上路径
) func main() {
pkg.MyPrinf("my pkg test")
fmt.Printf("test ok")
} //closure.go:6:2: cannot find package "pkg" in any of:
/root/golang/go/src/pkg (from $GOROOT)
/root/src/pkg (from $GOPATH) # 解决办法:将pkg包加个软连接到$GOROOT 或$GOPATH

golang之pkg(包)的更多相关文章

  1. Golang爬虫示例包系列教程(一):pedaily.com投资界爬虫

    Golang爬虫示例包 文件结构 自己用Golang原生包封装了一个爬虫库,源码见go get -u -v github.com/hunterhug/go_tool/spider ---- data ...

  2. 一键解决 go get golang.org/x 包失败

    问题描述 当我们使用 go get.go install.go mod 等命令时,会自动下载相应的包或依赖包.但由于众所周知的原因,类似于 golang.org/x/... 的包会出现下载失败的情况. ...

  3. 19-03【golang】strings包

    golang的strings包提供了字符串操作的一系列函数.下面做个简单介绍 函数 用法 备注 Compare(a,b sring) 比较两个字符串   Contains(s, substr stri ...

  4. 关于golang.org/x包问题

    关于golang.org/x包问题 由于谷歌被墙,跟谷歌相关的模块无法通过go get来下载,解决方法: git clone https://github.com/golang/net.git $GO ...

  5. Golang Gin 项目包依赖管理 godep 使用

    Golang Gin 项目包依赖管理 godep 使用 标签(空格分隔): Go 在按照github.com/tools/godep文档go get完包以后,调整项目结构为$GOPATH/src/$P ...

  6. golang 关于golang.org/x包问题

    关于golang.org/x包问题 由于谷歌被墙,跟谷歌相关的模块无法通过go get来下载,解决方法: git clone https://github.com/golang/net.git $GO ...

  7. Golang的json包

    encoding/json encoding/json是官方提供的标准json, 实现RFC 7159中定义的JSON编码和解码.使用的时候需要预定义struct,原理是通过reflection和in ...

  8. Golang官方log包详解

    Golang官方log包详解 以下全是代码, 详解在注释中, 请从头到尾看 // Copyright 2009 The Go Authors. All rights reserved. // Use ...

  9. 下了个pkg包的jenkins,的使用方法

    三.如何启动Jenkins1.最简单的方法是双击Jenkins的pkg包,一步一步点同意,默认8080端口2.使用命令行启动打开terminal,进入到war包所在目录,执行命令: java -jar ...

随机推荐

  1. Sublime Text 3 乱码解决

    步骤: 在Sublime Text里,按ctrl+`,打开Console,一次性输入如下代码: import urllib.request,os; pf = 'Package Control.subl ...

  2. UML图总结

    UML叙述 UML文档仅仅是设计与开发人员采用UML语言进行系统分析与设计的结果,并没有给出如何进行开发和采用何种开发流程,同样也不指导如何进行面向对象设计. UML文档描述了面向对象分析与设计的结果 ...

  3. oracle 库文件解决的方法 bad ELF interpreter: No such file or directory

    今天是2014-05-27,今天遇到一个lib问题,再次记录一下.这是一个案例,更是一种解决该问题的方法过程. 当我们在使用sqlplus 登陆unix数据库的时候,有可能出现类似:xxxxxx ba ...

  4. kettle工具同步数据乱码-Linux下乱码问题二

    将写好的kettle工程部署到Linux下后,同步的数据都成了乱码,幸运的是数据库有备份. 下面就说一下,kettle工程如何同步两端编码格式都是utf8的数据库. 我们只需要更改kettle数据库连 ...

  5. Linux 下mysql修改数据库存放目录方法和可能遇到的问题

    MySQL版本:5.6.23-enterprise-commercial-advanced ,使用rpm安装linux:Red Hat Enterprise Linux Server release ...

  6. web推送

    WEB消息推送框架 web-msg-sender是一款web长连接推送框架,采用PHPSocket.IO开发,基于WebSocket长连接通讯,如果浏览器不支持WebSocket则自动转用comet推 ...

  7. 开始我的.NET的学习旅程

    今天开始了我的.NET学习之旅,终于弄懂了.NET与C#的关系,一开始还以为它们就是一个东西,原来不是那样的,C#只是基于.NET平台环境下运行的一种语言,.NET不止可以运行C#语言,更可以运行其他 ...

  8. .net 链接oracle

    虽然EF6都快要出来了,但是对于Oracle数据库,仍然只能用DB first和Model First来编程,不能用Code First真是一个很大的遗憾啊. 好了,废话少说,我们来看看EF中是如何用 ...

  9. Android通过PHP连接MySQL(用到Json)

    1下载phpnow 如果已经有mysql 则需要换一个端口 在服务器机器上的phpnow安装目录E:\PHPnow-1.5.5\htdocs下新建一个test.php文件: 其中我用的数据库是test ...

  10. Swift语法基础入门三(函数, 闭包)

    Swift语法基础入门三(函数, 闭包) 函数: 函数是用来完成特定任务的独立的代码块.你给一个函数起一个合适的名字,用来标识函数做什么,并且当函数需要执行的时候,这个名字会被用于“调用”函数 格式: ...