Go-Package

来源:互联网 发布:mac怎么关闭开机密码 编辑:程序博客网 时间:2024/05/20 01:08

本文描述创建&使用package的一些内容。

要点:

  • GOPATH环境变量
  • package目录结构
  • 首字母大小写约定

GOPATH

要创建自定义的package,需要首先定义GOPATH环境变量。

这个GOPATH代表的目录是任意的,比如,D:\the_go_path

D:\examples>echo %GOPATH%D:\examples\the_go_pathD:\examples>

如果没有定义这个环境变量,会有异常提示:

D:\examples\shape>go installgo install: no install location for directory D:\examples\shape outside GOPATH        For more details see: go help gopathD:\examples\shape>

目录结构

在Introducing Go这本书中,没有明确写出package的目录结构。为此,请执行go help gopath命令获取详细内容。

尽管占用大量篇幅,但作者还是决定拷贝到这里:

D:\examples>go help gopathThe Go path is used to resolve import statements.It is implemented by and documented in the go/build package.The GOPATH environment variable lists places to look for Go code.On Unix, the value is a colon-separated string.On Windows, the value is a semicolon-separated string.On Plan 9, the value is a list.GOPATH must be set to get, build and install packages outside thestandard Go tree.Each directory listed in GOPATH must have a prescribed structure:The src directory holds source code.  The path below srcdetermines the import path or executable name.The pkg directory holds installed package objects.As in the Go tree, each target operating system andarchitecture pair has its own subdirectory of pkg(pkg/GOOS_GOARCH).If DIR is a directory listed in the GOPATH, a package withsource in DIR/src/foo/bar can be imported as "foo/bar" andhas its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a".The bin directory holds compiled commands.Each command is named for its source directory, but onlythe final element, not the entire path.  That is, thecommand with source in DIR/src/foo/quux is installed intoDIR/bin/quux, not DIR/bin/foo/quux.  The "foo/" prefix is strippedso that you can add DIR/bin to your PATH to get at theinstalled commands.  If the GOBIN environment variable isset, commands are installed to the directory it names insteadof DIR/bin. GOBIN must be an absolute path.Here's an example directory layout:    GOPATH=/home/user/gocode    /home/user/gocode/        src/            foo/                bar/               (go code in package bar)                    x.go                quux/              (go code in package main)                    y.go        bin/            quux                   (installed command)        pkg/            linux_amd64/                foo/                    bar.a          (installed package object)Go searches each directory listed in GOPATH to find source code,but new packages are always downloaded into the first directoryin the list.See https://golang.org/doc/code.html for an example.Internal DirectoriesCode in or below a directory named "internal" is importable onlyby code in the directory tree rooted at the parent of "internal".Here's an extended version of the directory layout above:    /home/user/gocode/        src/            crash/                bang/              (go code in package bang)                    b.go            foo/                   (go code in package foo)                f.go                bar/               (go code in package bar)                    x.go                internal/                    baz/           (go code in package baz)                        z.go                quux/              (go code in package main)                    y.goThe code in z.go is imported as "foo/internal/baz", but thatimport statement can only appear in source files in the subtreerooted at foo. The source files foo/f.go, foo/bar/x.go, andfoo/quux/y.go can all import "foo/internal/baz", but the source filecrash/bang/b.go cannot.See https://golang.org/s/go14internal for details.Vendor DirectoriesGo 1.6 includes support for using local copies of external dependenciesto satisfy imports of those dependencies, often referred to as vendoring.Code below a directory named "vendor" is importable onlyby code in the directory tree rooted at the parent of "vendor",and only using an import path that omits the prefix up to andincluding the vendor element.Here's the example from the previous section,but with the "internal" directory renamed to "vendor"and a new foo/vendor/crash/bang directory added:    /home/user/gocode/        src/            crash/                bang/              (go code in package bang)                    b.go            foo/                   (go code in package foo)                f.go                bar/               (go code in package bar)                    x.go                vendor/                    crash/                        bang/      (go code in package bang)                            b.go                    baz/           (go code in package baz)                        z.go                quux/              (go code in package main)                    y.goThe same visibility rules apply as for internal, but the codein z.go is imported as "baz", not as "foo/vendor/baz".Code in vendor directories deeper in the source tree shadowscode in higher directories. Within the subtree rooted at foo, an importof "crash/bang" resolves to "foo/vendor/crash/bang", not thetop-level "crash/bang".Code in vendor directories is not subject to import pathchecking (see 'go help importpath').When 'go get' checks out or updates a git repository, it now alsoupdates submodules.Vendor directories do not affect the placement of new repositoriesbeing checked out for the first time by 'go get': those are alwaysplaced in the main GOPATH, never in a vendor subtree.See https://golang.org/s/go15vendor for details.D:\examples>

要点:
- GOPATH下面有个src目录和pkg目录
- src放源码(.go文件),而go install会把生成的.a文件放在pkg目录下
- src下面又是一个个的目录,每个对应一个package
- 到src下面的对应package下执行 go install 命令,会自动安装package
- go install之后,就如同通常的情形来import。

示例

以前面Go-Interface的第一个例子说明package的使用方法。

创建目录结构

D:\examples\the_go_path>tree /F .文件夹 PATH 列表卷序列号为 5645-602FD:\EXAMPLES\THE_GO_PATH├─pkg└─src    └─shape            the_shape.goD:\examples\the_go_path>

这里取package的名字为shape。而package(shape)文件夹下面的go文件名没有什么要求,为此特意取名the_shape.go。

the_shape.go

package shape import "math"type Shape interface {    area() float64 }type Circle struct {    r float64 }func (c *Circle) area() float64 {    return math.Pi * c.r * c.r}type Rectangle struct {    length, width float64 }func (r *Rectangle) area() float64 {    return r.length * r.width;}func totalArea(shapes ... Shape) (total float64) {    total = 0     for _, shape := range shapes {        total += shape.area()    }    return }

go install

在package的目录下执行go install命令,这时会自动编译&链接,生成.a,并放在pkg目录下。如果go有编译错误,会有对应提示。

D:\examples\the_go_path\src\shape>go installD:\examples\the_go_path\src\shape>cd ../..D:\examples\the_go_path>tree /F .文件夹 PATH 列表卷序列号为 5645-602FD:\EXAMPLES\THE_GO_PATH├─pkg│  └─windows_amd64│          shape.a│└─src    └─shape            the_shape.goD:\examples\the_go_path>

调用新创建的package

package mainimport "fmt"import "shape"/*D:\examples>go run helloworld.go# command-line-arguments.\helloworld.go:17: implicit assignment of unexported field 'r' in shape.Circle literal.\helloworld.go:18: implicit assignment of unexported field 'length' in shape.Rectangle literal.\helloworld.go:18: implicit assignment of unexported field 'width' in shape.Rectangle literal.\helloworld.go:20: cannot refer to unexported name shape.totalArea.\helloworld.go:20: undefined: shape.totalAreaD:\examples>*/func main() {    circle := shape.Circle{5} // L17    ractangle := shape.Rectangle{3, 4} // L18                                       // L19    fmt.Println(shape.totalArea(&circle, &ractangle)) // L20}

通过编译错误信息,知道import “shape”已经生效了,即可以找到取名go install的shape包。但有新的问题。

为此,注意到Introducing Go Page81的如下说明:

In Go, if something starts with a capital letter, that means other packages (and programs) are able to see it. If we had named the function average instead of Average, our main program would not have been able to see it.

It’s a good practice to only expose the parts of our package that we want other packages using and hide everything else. This allows us to freely change those parts later without having to worry about breaking other programs, and it makes our package easier to use.

要点:

  • package中大写打头的是可以export的,小写打头的外面则不能访问
  • 通过这种首字母大小写可以起到public&private的作用。

修改后的代码

为了对比,这里新创建一个shape2文件,即新建一个名为shape2的包。然后修改这个目录下的the_shape.go文件:

  • package的名字改成shape2
  • 里边要导出的变量或函数改成首字母大写

    D:\examples\the_go_path>tree /F .
    文件夹 PATH 列表
    卷序列号为 5645-602F
    D:\EXAMPLES\THE_GO_PATH
    ├─pkg
    │ └─windows_amd64
    │ shape.a

    └─src
    ├─shape
    │ the_shape.go

    └─shape2
    the_shape.go

    D:\examples\the_go_path>

shape2/the_shape.go

package shape2import "math"type Shape interface {    Area() float64 }type Circle struct {    R float64 }func (c *Circle) Area() float64 {    return math.Pi * c.R * c.R}type Rectangle struct {    Length, Width float64 }func (r *Rectangle) Area() float64 {    return r.Length * r.Width;}func TotalArea(shapes ... Shape) (total float64) {    total = 0     for _, shape := range shapes {        total += shape.Area()    }    return }

go install

D:\examples\the_go_path>cd src/shape2D:\examples\the_go_path\src\shape2>go installD:\examples\the_go_path\src\shape2>cd ../..D:\examples\the_go_path>tree /F .文件夹 PATH 列表卷序列号为 5645-602FD:\EXAMPLES\THE_GO_PATH├─pkg│  └─windows_amd64│          shape.a│          shape2.a│└─src    ├─shape    │      the_shape.go    │    └─shape2            the_shape.goD:\examples\the_go_path>

修改调用函数

package mainimport "fmt"import "shape2"/*D:\examples\the_go_path>cd ..D:\examples>go run helloworld.go90.53981633974483D:\examples>*/func main() {    circle := shape2.Circle{5}    ractangle := shape2.Rectangle{3, 4}    fmt.Println(shape2.TotalArea(&circle, &ractangle))}

Document

对于自己创建的package,也可以用godoc命令。

注:为了显示下面的内容,已在源码上增加了一些注释信息。

D:\examples\the_go_path\src\shape2>godoc shape2use 'godoc cmd/shape2' for documentation on the shape2 commandPACKAGE DOCUMENTATIONpackage shape2    import "shape2"FUNCTIONSfunc TotalArea(shapes ...Shape) (total float64)TYPEStype Circle struct {    R float64}func (c *Circle) Area() float64    Area of a cirle.type Rectangle struct {    Length, Width float64}func (r *Rectangle) Area() float64type Shape interface {    Area() float64}    Area of the shape. User must implement it.D:\examples\the_go_path\src\shape2>
0 0
原创粉丝点击