1. 前言

在读docker及distribution源码的过程中遇到了很多坑,在此将这些坑记录下来,随时更新,在第二节中会给出更新的内容

2.包括的golang特性

  1. Godeps
  2. vendor
  3. _ 下划线
  4. 接口查询
  5. 包命名
  6. 结构体和接口

2.Godeps

  1. golang1.1版本之后,有了godep依赖管理工具,项目下新加了Godeps文件夹,其中含有项目依赖的包,记录包依赖的文件为Godeps.json,下面是一个例子,该例子为distribution2.1项目的Godeps,在github.com/docker/distribution可以直接用github.com/spf13/cobra中的结构而不用导入,可见ImportPath下的包可以直接调用Deps下含有的包:
{
    "ImportPath": "github.com/docker/distribution",
    "GoVersion": "go1.4.2",
    "Packages": [
        "./..."
    ],
    "Deps": [
        {
            "ImportPath": "github.com/AdRoll/goamz/aws",
            "Rev": "aa6e716d710a0c7941cb2075cfbb9661f16d21f1"
        },
        {
            "ImportPath": "github.com/AdRoll/goamz/cloudfront",
            "Rev": "aa6e716d710a0c7941cb2075cfbb9661f16d21f1"
        },
        {
            "ImportPath": "github.com/AdRoll/goamz/s3",
            "Rev": "aa6e716d710a0c7941cb2075cfbb9661f16d21f1"
        },
        {
            "ImportPath": "github.com/Azure/azure-sdk-for-go/storage",
            "Rev": "97d9593768bbbbd316f9c055dfc5f780933cd7fc"
        },
        {
            "ImportPath": "github.com/Sirupsen/logrus",
            "Comment": "v0.7.3",
            "Rev": "55eb11d21d2a31a3cc93838241d04800f52e823d"
        },
        {
            "ImportPath": "github.com/bugsnag/bugsnag-go",
            "Comment": "v1.0.2-5-gb1d1530",
            "Rev": "b1d153021fcd90ca3f080db36bec96dc690fb274"
        },
        {
            "ImportPath": "github.com/bugsnag/osext",
            "Rev": "0dd3f918b21bec95ace9dc86c7e70266cfc5c702"
        },
        {
            "ImportPath": "github.com/bugsnag/panicwrap",
            "Rev": "e5f9854865b9778a45169fc249e99e338d4d6f27"
        },
        {
            "ImportPath": "github.com/denverdino/aliyungo/oss",
            "Rev": "0e0f322d0a54b994dea9d32541050d177edf6aa3"
        },
        {
            "ImportPath": "github.com/denverdino/aliyungo/util",
            "Rev": "0e0f322d0a54b994dea9d32541050d177edf6aa3"
        },
        {
            "ImportPath": "github.com/docker/docker/pkg/tarsum",
            "Comment": "v1.4.1-3932-gb63ec6e",
            "Rev": "b63ec6e4b1f6f5c77a6a74a52fcea9564538c575"
        },
        {
            "ImportPath": "github.com/docker/libtrust",
            "Rev": "fa567046d9b14f6aa788882a950d69651d230b21"
        },
        {
            "ImportPath": "github.com/garyburd/redigo/internal",
            "Rev": "535138d7bcd717d6531c701ef5933d98b1866257"
        },
        {
            "ImportPath": "github.com/garyburd/redigo/redis",
            "Rev": "535138d7bcd717d6531c701ef5933d98b1866257"
        },
        {
            "ImportPath": "github.com/gorilla/context",
            "Rev": "14f550f51af52180c2eefed15e5fd18d63c0a64a"
        },
        {
            "ImportPath": "github.com/gorilla/handlers",
            "Rev": "60c7bfde3e33c201519a200a4507a158cc03a17b"
        },
        {
            "ImportPath": "github.com/gorilla/mux",
            "Rev": "e444e69cbd2e2e3e0749a2f3c717cec491552bbf"
        },
        {
            "ImportPath": "github.com/inconshreveable/mousetrap",
            "Rev": "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
        },
        {
            "ImportPath": "github.com/mitchellh/mapstructure",
            "Rev": "482a9fd5fa83e8c4e7817413b80f3eb8feec03ef"
        },
        {
            "ImportPath": "github.com/ncw/swift",
            "Rev": "ca8cbbde50d4e12dd8ad70b1bd66589ae98efc5c"
        },
        {
            "ImportPath": "github.com/noahdesu/go-ceph/rados",
            "Comment": "v.0.3.0-29-gb15639c",
            "Rev": "b15639c44c05368348355229070361395d9152ee"
        },
        {
            "ImportPath": "github.com/spf13/cobra",
            "Rev": "312092086bed4968099259622145a0c9ae280064"
        },
        {
            "ImportPath": "github.com/spf13/pflag",
            "Rev": "5644820622454e71517561946e3d94b9f9db6842"
        },
        {
            "ImportPath": "github.com/stevvooe/resumable",
            "Rev": "51ad44105773cafcbe91927f70ac68e1bf78f8b4"
        },
        {
            "ImportPath": "github.com/yvasiyarov/go-metrics",
            "Rev": "57bccd1ccd43f94bb17fdd8bf3007059b802f85e"
        },
        {
            "ImportPath": "github.com/yvasiyarov/gorelic",
            "Comment": "v0.0.6-8-ga9bba5b",
            "Rev": "a9bba5b9ab508a086f9a12b8c51fab68478e2128"
        },
        {
            "ImportPath": "github.com/yvasiyarov/newrelic_platform_go",
            "Rev": "b21fdbd4370f3717f3bbd2bf41c223bc273068e6"
        },
        {
            "ImportPath": "golang.org/x/crypto/bcrypt",
            "Rev": "c10c31b5e94b6f7a0283272dc2bb27163dcea24b"
        },
        {
            "ImportPath": "golang.org/x/crypto/blowfish",
            "Rev": "c10c31b5e94b6f7a0283272dc2bb27163dcea24b"
        },
        {
            "ImportPath": "golang.org/x/net/context",
            "Rev": "1dfe7915deaf3f80b962c163b918868d8a6d8974"
        },
        {
            "ImportPath": "gopkg.in/check.v1",
            "Rev": "64131543e7896d5bcc6bd5a76287eb75ea96c673"
        },
        {
            "ImportPath": "gopkg.in/yaml.v2",
            "Rev": "bef53efd0c76e49e6de55ead051f886bea7e9420"
        }
    ]
}

3.vendor

  1. golang1.5版本后加入vendor依赖包管理工具,还在试用阶段,需要导入环境变量export GO15VENDOREXPERIMENT=1,这样做后就可以直接在编写go代码时导入vendor目录下的包而不用从gopath开始,比如docker1.9项目中,import “github.com/docker/distribution/digest”导入的就是vendor目录下的对应包

4._下划线

  1. _下划线在golang中的使用
    • 一种情况是占位用的,方法返回两个结果,而你只想要一个结果,那另一个就用 _ 占位,而如果用变量的话,不使用,编译器是会报错的。
    • 还有一种情况时类似于 import _ “fmt” 这种,import 一个包进来,但是不使用,只是让包自己初始化一下,运行一下包内部的init()函数,否则导入包不用也是会报错的。但也要记住,这种情况下是不用调用包内其他的函数或者变量的。

5.查询

5.1接口查询

package two
type IStream insterface {
    Read(buf []byte) (n int, err error)
    Write(buf []byte) (n int, err error)
}
package main
var file1 Writer = new(File)
if file5, ok := file1.(two.IStream); ok {
}

上述代码检查file1接口指向的对象是否实现了two.IStream接口,如果实现了,则初始化file5并执行特定代码。

5.2类型查询

在Go语言中,还可以更加直截了当地询问接口指向的对象实例类型,例如:

var v1 interface{} = ...
switch v := v1.(type) {
    case int:     //现在v的类型是int
    case string:  //现在v的类型是string
    ...
}

6. 包命名

项目的同一个目录下只能有一个包名,所有文件得用这个包名,不然会报错。

7. 结构体和接口

  • 当结构体的成员变量是结构体时,如果该结构体没有赋值给具体的变量,那么值就顺延至新结构体;如果赋值给了新变量,那么新变量就是新结构体的成员。
  • 当一个结构体实现了接口的全部函数时,该结构就实现了这个接口,不一定要显式声明
  • 接口类型作为具体的结构体成员,当为该结构体的接口类型赋值时赋的是已经实现了接口类型的结构

8. 作者介绍

梁明远,国防科大并行与分布式计算国家重点实验室(PDL)应届研究生,14年入学伊始便开始接触docker,准备在余下的读研时间在docker相关开源社区贡献自己的代码,毕业后准备继续从事该方面研究。邮箱:liangmingyuanneo@gmail.com

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐