main包申明的程序是可运行的。
包是函数和数据的集合,将有相关的鹅的函数和数据放在统一的文件目录进行管理,每个包都可以作为独立的单元维护并提供给其他的项目 进行使用。
声明:
GO源文件都需要在开头使用package声明所在的包,包名告知编译器哪些包的源代码用于编译库文件,其次包名用于限制包内成员包内成员对外的可见性,最后包名用于在包外对公开成员的访问
包名使用简短的小写字母,常与所在的目录名保持一致,一个包中可以由多个 go源文件,但是必需使用相同的包名。
在Go语言里面是通过首字母的大小写来定位包外部可不可以被访问 。
main包与main函数
main包用于声明告知编译器将包编译为二进制可执行文件
在main包中的main函数是程序的入口,无返回值,无参数
init函数
init函数是初始化包的时候使用的, 无返回值,无参数,建议每个包只定义一个,init函数在import包时自动调用,(const -> var ->init )
GOPATH + vendor 机制
vendor
将项目依赖的包拷贝到项目下的vendor 目录,在编译时使用项目下的vendor目录中的包进行编译
解决问题:
依赖的外部包过多,在使用第三方包的时候需要go get进行下载
第三方包在go get下载后不能保证开发和编译时版本的兼容 。
包 搜索顺序
在当前包上级目录下查找GOPATH/src/vendor目录
在GOPATH目录下查找
在GOROOT目录下查找
第三方包
可以借助go get工具下载和安装第三方包及其依赖,需要安装与第三方包匹配的代码管理工具,比如git svn 等
常用参数:
-d :仅下载依赖包
-u: 更新包并安装
-x: 打印执行的命令
-v:打印构建的包
-insecure : 允许使用http协议下载包、
第三方包查找的地址 :
https://godoc.org
https://gowalker.org/
包-Go包管理
Go modules 机制
优势 :
不用设置 GOPATH ,代码可以任意放置
自动下载依赖管理
版本控制
不允许使用相对导入
replace机制
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文件
-require =pakcage@version
-replace
=old_package@version=new_package@version
可以使用-replace功能将包替换为本地包,实现相对导入功能
单元测试-Test函数
测试函数需要导入testing包,并
编写代码
目录结构
package calc func AddXXX(x, y int) int { if x < 0 { return x + y } else { return x } } func Multi(x, y int) int { return x * y }
package calc import ( "testing" ) func TestAdd(t *testing.T) { if 4 != AddXXX(1, 3) { t.Error(" 1 + 3 != 4 ") } } func TestAddFlag(t *testing.T) { if -1 != AddXXX(-1, 3) { t.Error("不相同") } }
go test ./… -coverprofile=cover.out
【结果输出】
? go_learn/20211104/codes/src/testcalc [no test files]
— FAIL: TestAdd (0.00s)
calc_test.go:9: 1 + 3 != 4
— FAIL: TestAddFlag (0.00s)
calc_test.go:16: 不相同
FAIL
coverage: 75.0% of statements
FAIL go_learn/20211104/codes/src/testcalc/calc 0.004s
FAIL
go tool cover -html cover.out
展示75%的代码覆盖率
命令行参数
package main import ( "flag" "fmt" ) func main() { var port int // 绑定命令行参数与变量关系 var host string var help bool flag.IntVar(&port, "P", 22, "ssh port") flag.StringVar(&host, "H", "127.0.0.1", "请输入ip") flag.BoolVar(&help, "h", false, "help") flag.Usage = func() { fmt.Println("usage flag arsg [-H 127.0.0.14 ] [-P 22][-v]") flag.PrintDefaults() } // 解析命令行参数 flag.Parse() fmt.Println(help) if help { fmt.Println("-------------------") flag.Usage() } else { fmt.Println(host, port) fmt.Println(flag.Args()) } }
package main import ( "flag" "fmt" ) func main() { port := flag.Int("P", 22, "ssh port") host := flag.String("H", "127.0.0.1", "请输入ip") help := flag.Bool("h", false, "help") fmt.Printf("%T %T %T \n", *port, *host, *help) // int string bool flag.Usage = func() { fmt.Println("usage flag arsg [-H 127.0.0.14 ] [-P 22][-v]") flag.PrintDefaults() } // 解析命令行参数 flag.Parse() fmt.Println(help) if *help { fmt.Println("-------------------") flag.Usage() } else { fmt.Println(host, port) fmt.Println(flag.Args()) } }
go run flagargsv1.go -h -P 22
时间
package main import ( "fmt" "time" ) func main() { now := time.Now() fmt.Printf("%T \n", now) //time.Time fmt.Printf("%v \n", now) //2021-11-07 16:45:30.621285 +0800 CST m=+0.000053567 // 2000/01/02 08:10:10 // 2006年 // 01月 // 02天 // 24进制小时 15 // 分钟 04 // 秒 05 fmt.Println(now.Format("2006/01/02 15:04:05")) //2021/11/07 16:45:30 fmt.Println(now.Format("2006-01-02 15:04:05")) //2021-11-07 16:45:30 fmt.Println(now.Format("2006-01-02")) //2021-11-07 fmt.Println(now.Format("15:04:05")) fmt.Println(now.Unix()) //1636274730 fmt.Println(now.UnixNano()) //1636274730621285000 xx, err := time.Parse("2006/01/02 03:04:05", "2006/01/02 03:04:05") fmt.Println(err, xx) // 2006-01-02 03:04:05 +0000 UTC t := time.Unix(0, 0) fmt.Println(t) //1970-01-01 08:00:00 +0800 CST d := now.Sub(t) fmt.Println(d) //454520h51m59.778108s fmt.Printf("%T \n", d) //time.Duration // time.Second // time.Hour // time.Minute // timeMillisecond fmt.Println(time.Now()) //2021-11-07 16:54:33.066575 +0800 CST m=+0.000369435 time.Sleep(time.Second * 1) fmt.Println(time.Now()) //2021-11-07 16:54:38.070339 +0800 CST m=+5.004314271 now3 := now.Add(time.Hour * 3) fmt.Println(now, now3) //2021-11-07 16:55:47.174147 +0800 CST m=+0.000093460 2021-11-07 19:55:47.174147 +0800 CST m=+10800.000093460 d, err = time.ParseDuration("3h2m4s") fmt.Println(err, d) // 3h2m4s fmt.Println(d.Hours()) //3.0344444444444445 fmt.Println(d.Minutes()) //182.06666666666666 fmt.Println(d.Seconds()) //10924 }
hash算法
package main import ( "crypto/md5" "encoding/hex" "fmt" ) func main() { x := md5.Sum([]byte("i amkk")) y := fmt.Sprintf("%X \n", x) fmt.Println(y) // z := hex.EncodeToString(x[:]) fmt.Println(z) m := md5.New() m.Write([]byte("i")) m.Write([]byte(" amkk")) fmt.Printf("%x\n", m.Sum(nil)) }
base64
package main import ( "encoding/base64" "fmt" ) func main() { x := base64.StdEncoding.EncodeToString([]byte("i am kk")) fmt.Println(x) bytes, err := base64.StdEncoding.DecodeString(x) fmt.Println(string(bytes), err) }
日志 :
package main import "log" func main() { log.Printf("我是一个人") log.Printf("我是一个人") log.SetFlags(log.Flags() | log.Lshortfile) //prefix2021/11/07 20:30:46 logx.go:15: 我是fatalf日志z //log.SetFlags(log.Flags() | log.Llongfile) log.SetPrefix("prefix") //在日志前面加上前缀 prefix2021/11/07 20:29:59 /Users/quyixiao/go/src/go_learn/20211107/logx/logx.go:14: 我是fatalf日志z //打印一个日志,并且触发一个panic //log.Panicf("我是panic日志 :%s","y") log.Fatalf("我是fatalf日志%s", "z") log.Fatalf("我是fatalf日志%s", "z") //打印之后直接退出 }
2021/11/08 11:35:48 我是一个人
2021/11/08 11:35:48 我是一个人
prefix2021/11/08 11:35:48 logx.go:15: 我是fatalf日志z