golang之pkg(包)

一、概述

  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

 1 // The jpeg command reads a PNG image from the standard input
 2 // and writes it as a JPEG image to the standard output.
 3 package main
 4 import (
 5   "fmt"
 6   "image"
 7   "image/jpeg"
 8   _ "image/png" // register PNG decoder
 9   "io"
10   "os"
11 ) 12 func main() {
13   if err := toJPEG(os.Stdin, os.Stdout); err != nil {
14     fmt.Fprintf(os.Stderr, "jpeg: %v\n", err)
15     os.Exit(1)
16   }
17 }
18 func toJPEG(in io.Reader, out io.Writer) error {
19   img, kind, err := image.Decode(in)         //这里可能需要匿名导入
20   if err != nil {
21     return err
22   }
23   fmt.Fprintln(os.Stderr, "Input format =", kind)
24   return jpeg.Encode(out, img, &jpeg.Options{Quality: 95})
25 }

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

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

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

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

 四、自定义自己的包:

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

1 ├── pkg
2 │   └── myprint.go
3
4 //myprint.go
5 package pkg
6 import "fmt"
7 func MyPrintf(in string) {
8     fmt.Printf("%s", in)
9 }

  在main包中测试:

 1 package main
 2 import  (
 3      "fmt"
 4      "./pkg"     //带上路径
 5 )
 6
 7 func main() {
 8     pkg.MyPrinf("my pkg test")
 9     fmt.Printf("test ok")
10 }
11
12 //测试ok
13 稍作修改:
14 package main
15 import  (
16      "fmt"
17      "pkg"     //不带上路径
18 )
19
20 func main() {
21     pkg.MyPrinf("my pkg test")
22     fmt.Printf("test ok")
23 }
24
25 //closure.go:6:2: cannot find package "pkg" in any of:
26     /root/golang/go/src/pkg (from $GOROOT)
27     /root/src/pkg (from $GOPATH)
28
29 # 解决办法:将pkg包加个软连接到$GOROOT 或$GOPATH

 

时间: 2024-11-03 23:34:26

golang之pkg(包)的相关文章

go语言编程-Golang的odbc包install出错

问题描述 Golang的odbc包install出错 用Go程序写代码,用到odbc包,这个包不在标准库里,所以到https://github.com/weigj/go-odbc这里下载了一个包.然而在go install的过程中出现了下面的错误: 似乎这是odbc包里本身就有的错误,但是这个包应该已经创建过几年了,很多人用过,从来没有人出现过这种错误,百度也找不到答案,这是为什么呢? PS:程序运行的时候也出现了同样的报错信息 解决方案 首先要看这个包对应的os,然后就是包是否有依赖,还有go

golang语言strconv包使用例子

golang strconv包提供了字符串和基本数据类型之间的转换操作. 1.默认提供了1个常量IntSize和两个变量ErrRange和ErrSyntax. package main   import (  "strconv"  "fmt" )   func main()  {  //IntSize是int或uint类型的字位数.  fmt.Println(strconv.IntSize)  //ErrRange表示超出目标类型表示范围.[var ErrRange

golang 的glide包管理使用技巧教程

安装glide wemall git:(master) go get github.com/Masterminds/glide wemall git:(master) go install github.com/Masterminds/glide wemall git:(master) glide init wemall git:(master) glide up [INFO] Loading mirrors from mirrors.yaml file[INFO] Downloading de

golang标准库flag包实现实现命令行解析

golang中flag包是用来对命令行参数解析的,看下面一个简单例子: package main   import (  "fmt"  "flag" )   func main() {    //使用flag.String()函数注册flag,得到结果conf指针  var conf = flag.String("f", "test.conf", "Specify the config file")    

在Golang中使用C语言代码实例_Golang

cgo 使得在 Golang 中可以使用 C 代码. Hello World 为了有一个较为直观的了解,我们来看一个简单的例子,创建文件 main.go: 复制代码 代码如下: package main   /* #include <stdio.h>   void sayHi() {     printf("Hi"); } */ import "C"   func main() {     C.sayHi() } 执行程序: 复制代码 代码如下: go

Golang极简入门教程(一):基本概念_Golang

安装 Golang 在 http://golang.org/dl/ 可以下载到 Golang.安装文档:http://golang.org/doc/install. Hello Go 我们先创建一个文件 hello.go: 复制代码 代码如下: package main   import "fmt"   func main() {     fmt.Printf("hello Golang\n"); } 执行此程序: 复制代码 代码如下: go run hello.g

Golang 退出chroot环境的方法

chroot()是用linux的系统函数,能改变程序运行时参考的根目录.安装系统或者通过引导盘进入恢复系统时,可以通过chroot()修复GRUB,或者安装软件. Golang的syscall包提供Chroot()方法. 但进入chroot环境后,如何退出呢?目前我就碰到这个需求.翻遍syscall包,也没看到直接的退出方式.Google后发现,不止我一个人想这么做.有篇文章 给出了python的hack方案.照猫画虎,我用go试着做了一遍: // hold our real root's fi

go-tour练习解答

go-tour对于想学习golang的人来说是一个很好的教程. 首先go-tour是有web版本,但是需要FQ.如果不能FQ的,也可以在google code上自己下载go-tour源码,go build,run一下,在自己的机器上就可以跑这个教程了. 提醒下,如果是后者,这篇文章中的程序对应的import包就需要进行相应修改了. 下面给出我的go-tour中的Exercise的解答(在web上已经测试通过) Exercise: Loops and Functions 第一个循环10次: pac

Go语言_反射篇

Go语言的基本语法的使用已经在前几篇陆陆续续学完了,下面可能想写一些Go的标准库的使用了. 先是reflect库. reflect库的godoc在http://golang.org/pkg/reflect/ Type和Value 首先,reflect包有两个数据类型我们必须知道,一个是Type,一个是Value. Type就是定义的类型的一个数据类型,Value是值的类型 具体的Type和Value里面包含的方法就要看文档了: http://golang.org/pkg/reflect/   这