go学习笔记(包和工具)

Package:

  1. 每一组文件被称为一个包,包关键词 package,如:package net/http
  2. 所有的go文件都必须在第一行声明包。
  3. 同一个文件目录下的go文件必须声明同一个包。
  4. 包的名称尽量简短,保持和目录名一致,如:net/http net/cgi等。net目录下的http和cgi目录都是不同的包。
  5. main包,每一个go应用程序都必须有一个main包。
  6. main包必须都唯一的main函数作为唯一的入口。

Import

  1. 导入多个包用括号括起来,如:
package main
import(
    _ "github.com/astaxie/beego/session/mysql"
  . "github.com/smartystreets/goconvey/convey"
    "net/http"
    "myfmt mylib/fmt"
    "fmt"
)
  1. 导入的多个包的时候,go会首先查找标准库中的包(/usr/local/go),其次查找GOPATH下的包。
  2. 包导入可以指定url(github.com/astaxie/beego/session/mysql)
  3. 每个包导入进来可以起个别名,在左边起个名字,如果包不用go编译的时候会报错。
  4. 如果包导进来不想用,只是作为初始化,比如数据库初始化,可以指定 _ 符号忽略它。
  5. 包名字设置为.代表为本地包在调用的时候,不需要使用包名.函数调用,直接函数()调用
func main() {
    //fmt.Println("hello") //用包的别名调用包的方法
    Println("hello") //省略包名直接调用,点代表省略包名调用,即本地包。
}
  1. 每个包可以包含多个init初始化函数。init中可以做包的初始化,在main函数执行前执行。

Command

Go --help 可以看到所有的命令。

  1. go build 后边可以跟包名称(包名和目录名一般一样),go文件,也可以跟3个点。表示匹配所有包。
go build . //当前目录
go build github.com/astaxie/beego/session/mysql
go build github.com/astaxie/beego/... //表示匹配beego下面所有的包。
  1. go run 运行go文件,包括编译的步骤。如:go run xxx.go

  2. go vet可以检测代码常见的错误,但不包含复杂的逻辑错误,提交代码前执行go vet就跟php 提交前执行php -l一样是个好习惯。

  3. gofmt 格式化代码。

  4. godoc支持命令,http服务等查看文档,也支持把自己写的代码生成成文档包含在官方文档里(规则网上查)。go doc 和godoc是两个东西。可以执行help查看具体使用方法。

go doc fmt Print //查看fmt包print方法
godoc --http=:81//启动一个端口为81的go http服务,浏览器localhost:81访问
  1. go get下载包到本地。很多包需要翻墙,可以指定阿里的镜像。GOPROXY="https://mirrors.aliyun.com/goproxy/"
go get -u github.com/astaxie/beego
  1. go env可以查看go的环境变量。
  2. go mod 管理go导入的包,go mod init 会在项目根目录下生成go.mod文件,运行程序的时候go mod会自动去查找下载需要的依赖包。
  3. go test 运行单元测试命令,可以go help test查看具体的用法。
go test -v ./tests -run=^TestPurpose$

指针 (指针类型,指针变量,指针地址)

go语言中的指针类型变量即拥有指针高效访问的特点,又不会发生指针偏移,从而避免了非法修改关键性数据的问题。同时,垃圾回收也比较容易对不会发生偏移的指针进行检索和回收。go的指针有2个核心的概念:

  1. 类型指针,允许对这个指针类型的数据进行修改,传递数据可以直接使用指针,而无须拷贝数据,类型指针不能进行偏移和运算。
  2. 切片,由指向起始元素的原始指针、元素数量和容量组成。
var ptr *ptr-type //ptr称为指针变量,ptr-type称为指针的类型。
var var_name var_type // var_name变量名 var_type变量类型。
ptr = &var_name //代表指针变量的值是var_name在内存中的存储地址,也就是指针变量的地址
var pptr **ptr-type //代表指向指针的指针变量,意思就是指针变量存储的是另一个指针变量的地址。
//例如:
pptr = &ptr //ptr本身存储的是var_name的地址,&ptr代表指针的地址,赋值给pptr,那么pptr存储的就是指针变量的指针地址。

举个栗子。

之前开发的时候遇到过一个问题。如下:

//获取列表
func PaperTypeList(paperTypes *[]PaperType, count *int64, limit, offset int64, name string) error {
    query := getPaperQuery(name)
    //countResult := query.Count(&count) //错误的地方。
  countResult := query.Count(count)
    if countResult.Error != nil {
        if countResult.RecordNotFound() {
            return &exceptions.Empty
        }
        return &exceptions.Persistence
    }
    query = getPaperQuery(name)
    switch {
    case limit == -1:
    case limit > 0:
        query = query.Limit(limit)
    case limit > 100:
        limit = 100
        query = query.Limit(limit)
    default:
        limit = setup.PageSize
        query = query.Limit(limit)
    }
    if offset > 0 {
        query = query.Offset(offset)
    }
    result := query.Find(&paperTypes)
    if result.Error != nil {
        if result.RecordNotFound() {
            return &exceptions.Empty
        }
        return &exceptions.Persistence
    }
    return nil
}

//调用
var (
        paperTypes []models.PaperType
        total      int64
    )
if err := models.PaperTypeList(&paperTypes, &total, limit, offset, label); err != nil {
        self.Raise(err)
}

在上面错误的地方,我传了个地址进去,导致最终获取的count始终是0,单元测试过不了,debug的时候才发现count的地址发生了变化。

上面的原因就是count是个指针变量,然后query.Count(&count)时,等于把指向指针的指针变量传过去了。

你可能感兴趣的:(go学习笔记(包和工具))