go 包

go中最小分发单位

存放变量函数数据

每个包都可以作为独立的但愿维护并提供给其他项目进行使用

包的定义调用

定义:

main包:可运行

非main包:库文件

包名尽量小写,常与目录名保持一致

一个包中由多个go文件组成,每个go文件需要写入package 包名

文件组成:

bin:二进制程序发布目录 go install pkgpath -- > main包

pkg:库文件发布目录,go install pkgpath --> 非main包

src:源码目录,包目录

执行命令:

go build:构建编译,当前目录生成.exe文件,不会发布到bin目录

go install:发布程序到bin目录,并会生成.exe文件

go install -a:强制编译所有的库

build后的文件保存在GoPath的bin目录下中

go env:查看环境信息

go run: 运行二进制文件

go get github/tcy110!/project: 将项目下载到本地

包的作用:

  1. 包可以区分相同名字的函数以及变量等标识符
  2. 当程序庞大,将程序不同部分写在不一样的文件夹(包)中,方便对项目的管理
  3. 控制函数已经变量的访问范围,可以通过将其放置在不同的包来实现。

包的引入:

  1. import导入语句通常放在源码文件开头包声明语句的下面
  2. 导入包需要用双引号包裹起来
  3. 包名是从GOPAH/src/后开始计算的,使用/进行路径分隔

包变量:

  1. 如需包中变量被其他包能使用,那变量名首字母需要大写
// 在src目录下新建两个dir,为pkg & testpkg
// 目录中分别存放pkg/version.go & testpkg/main.go

// pkg/version.go
package pkg					// 指定当前包名
const Version = 1.1

// testpkg/main.go
package main
import (
	"fmt"
	"pkg"					// 导入和testpkg同级目录下的pkg包
     localpkg "pkg" 		                // 为pkg包设置别名
     _ "pkg"				        // 导入包不使用,和初始化函数一起使用
     . "pkg"				        // 点导入方式,后面直接可以用变量名,不用加包名,少用
)

func main() {
	fmt.Println(pkg.Version)	        // 直接使用导入包中的常量
    fmt.Pringln(localpkg.Version)               // 使用别名导入
}

mian包与main函数

main包用于声明告知编译器将包编译为二进制可执行文件

在main包中的main函数是程序的入口,无返回值,无参数,一个包中只能有一个main函数

包类型:

可执行程序:main

库:其他包文件

init函数

init函数是初始化包使用,无返回值,无参数,建议每个包只定义一个,init函数在import包时被自动调用, 对包中数据初始化。import pkgname时被执行

func init() {}

(包const - > 包var - > init)

一个包中可以有多个初始化函数

gopath+vendor

当存在依赖,有使用别人相关库,为了避免相关库被删除,可以将包拷贝至当前项目的verdor目录下

这样就算被依赖的库删除,我的编译也依然能通过

顺序:当前执行文件下找vendor --> 上一级目录下找vendor --> GOPATH/src/vendor --> GOROOT

注意:

gomode和gopath只能二选一

当使用gopath,下载包需要使用go get

当使用gomodule,无需对包下载,直接go build会自动下载依赖

go get 参数

-d :仅下载依赖包

-u:更新包并安装

-x:打印执行的命令

-v 打印构建的包

-insecure:允许使用http下载

第三方包查找地址:

htts://godoc.org

https://gowalker.org 常用

go module

优势:

  1. 不用设置GOPATH,代码可以放置任意位置
  2. 自动下载依赖管理
  3. 版本控制
  4. 不允许使用相对导入
  5. replace机制
// 初始化,目录下会存在一个go.mod文件
go mod init gihub.com/tcy/testmod

// 将不被识别编译的包将手动添加,这样go  build就不会报错
// replace可以将获取不到的包,通过另外的路径去获取,执行后会go.mod中添加相关指令
go mod edit -replace=golang.org/x/crypto=github.com/golang/cryptop@laster

// go.mod中的require
会将依赖的库写入

// 常用命令:
go mod tidy:整理依赖模块(添加新增的,删除未使用的)
go mod vendor:将依赖模块拷贝到模块中的vendor目录
go build:编译当前模块
go build ./...:编译当前目录下的所有模块
go build -mod=vendor:使用当前模块下的vendor目录中的包进行编译
go mod download:仅下载第三方模块
go mod grapha: 打印所有第三方模块
go list -m -json all: 显示所有模块信息
go mod edit:修改go.mod文件
	-replace功能将包替换为本地包,实现相对导入

// go.sum文件

单元测试

对哪个功能需要测试,相当于新建一个go文件,写上功能测试函数。也叫测试用例

测试代码文件命名: _test.go

测试函数命名:Test开头

函数参数: *testing.T

函数的返回值:无

函数体:t.Error 或者 t.Errorf

go test 项目/包名:执行测试操作

go test 项目/包名 -converprofile-cover.out:获取覆盖测试率

go tool cover -html cover.out:图形界面查看测试覆盖率

基准测试

也就是性能测试

函数要求:

​ 命名:Beachmark开头

​ 参数:*testing.B

​ 返回值:无

​ 函数体:循环n次执行代码

命令行参数

// 代码,返回切片,一个参数为脚本路径
func main() {
	fmt.Println(os.Args)
}

// 终端执行
go run args.go test aaa bbb ccc			
// 输出:[C:\Users\CAIYU~1.TAN\AppData\Local\Temp\go-build2466932673\b001\exe\args.exe test aaa bbb ccc]
  • 接收命令行参数(方式一)
// 函数代码
func main() {
	var port int
	var host string
	var verbor bool
	var help bool
	// 绑定命令行参数与变量关系
	flag.IntVar(&port, "p", 22, "ssh port")
	flag.StringVar(&host, "H", "127.0.0.1", "ssh host")
	flag.BoolVar(&verbor, "v", false, "detail log")
	flag.Usage = func() {
		fmt.Println("usage: flagargs [-H 127.0.0.1] [-p 22] [-v]")
		flag.PrintDefaults()		// 打印默认帮助信息
	}

	// 解析命令行参数
	flag.Parse()
	if help {
		flag.Usage()
	} else {
		fmt.Println(port, host, verbor)
	}

}

// 终端执行
PS F:\GoLand\Go-project\go1.18.1\src\stdpkg> go run flagargs.go -h
usage: flagargs [-H 127.0.0.1] [-p 22] [-v]
  -H string
        ssh host (default "127.0.0.1")
  -p int
        ssh port (default 22)
  -v    detail log

  • 接收命令行参数(方式二)
func main() {
	// 绑定命令行参数与变量关系
	port := flag.Int("p", 22, "ssh port")
	host := flag.String("H", "127.0.0.1", "ssh host")
	verbos := flag.Bool("v", false, "detail log")

	flag.Usage = func() {
		fmt.Println("usage: flagargs [-H 127.0.0.1] [-p 22] [-v]")
		flag.PrintDefaults()
	}

	// 解析命令行参数
	flag.Parse()
	fmt.Printf("%T %T %T", port, host, verbos)    // *int *string *bool 获取指针类型
	fmt.Printf("%v %v %v", *port, *host, *verbos) // 22 127.0.0.1 false
}

时间模块

func main() {
	now := time.Now()
	fmt.Printf("%T\n", now)     // time.Time
	fmt.Printf("%v\n", now)     // 2022-05-01 11:32:12.8953429 +0800 CST m=+0.004311701

	fmt.Println(time.Now())
	time.Sleep(time.Second * 5) // 让程序休眠5秒
	fmt.Println(time.Now())

	t := now.Add(3 * time.Hour) // 计算当前时间往后3个小时的时间
	fmt.Println(t)
    
    // 时间转换 now.Format
}

hash算法

  • md5计算的两种方式:
func main() {
	bytes := md5.Sum([]byte("i'amkk"))         // 计算md5
	x := fmt.Sprintf("%x", bytes)

	fmt.Println(x)                            // 转换为16进制
	fmt.Println(bytes)                        // [206 194 148 58 249 235 181 164 226 103 56 121 60 143 13 114]
	fmt.Println(hex.EncodeToString(bytes[:])) // 转换为16进制

	m := md5.New() // 当需要计算的md5过大,可以拆解
	m.Write([]byte("i'am"))
	m.Write([]byte("kk"))

	fmt.Printf("%x\n", m.Sum(nil)) // cec2943af9ebb5a4e26738793c8f0d72
}
  • base64编码解码
// base64
	// 将字节数组转换为base64类型的字符串
	x := base64.StdEncoding.EncodeToString([]byte("I'am kk"))
	fmt.Println(x) // SSdhbSBraw==

	bytes, err := base64.StdEncoding.DecodeString(x) // 解码
	fmt.Println(string(bytes), err)                  // 解码结果转换为字符串

日志

func main() {
	log.Printf("我是print日志: %s", "x") // 2022/05/01 14:57:18 我是print日志: x

	log.SetPrefix("prefix:")                     // 后续的日志打印都会加上前缀
	// Falgs(获取当前日志标签) & SetFlags(设置)
	//log.SetFlags(log.Flags() | log.Lshortfile) // 后续打印日志加上文件名
	log.SetFlags(log.Flags() | log.Llongfile)    // 后续答应日志加上日志路径

	//log.Panic("我是Panic日志:%s", "y")         // 不常用

	log.Fatalf("我是Fatalf日志:%s", "z")         // 和printf结果一样,不过会退出

}

隐藏密码

import (
	"fmt"
	"github.com/howeyc/gopass"
)

func main() {
	fmt.Print("请输入密码:")
	bytes, _ := gopass.GetPasswd()
	fmt.Println(string(bytes))
}
posted @ 2022-05-01 17:37  元气少女郭德纲!!  阅读(81)  评论(0编辑  收藏  举报