目录
一、用go mod管理工程 二、包引入规则 三、init调用链 四、可见性 五、标准库 1 - 时间函数 2 - 数学计算 3 - I/O操作 4 - 编码
一、用go mod管理工程
初始化项目 :go mod init $module_name
,$module_name和目录名可以不一样。上述命令会生成go.mod文件
module main
go 1.19
require gonum. org/ v1/ gonum v0. 12.0
包查找规则 :Go依次从当前项目、GOROOT、GOPATH下寻找依赖包
从当前go文件所在的目录逐级向上查找go.mod文件(假设go.mod位于目录mode_path下),里面定义了module_name,则引入包的路径为"module_name/包相对于mode_path的路径" go标准库提供的包在GOROOT/src下 第三方依赖包在GOPATH/pkg/mod下 包管理命令
从go1.7开始,go get只负责下载第三方依赖包,并把它加到go.mod文件里,由go install负责安装二进制文件
go get github.com/mailru/easyjson
会在GOPATH/pkg/mod目录下生成github.com/mailru/easyjson目录go install github.com/mailru/easyjson/easyjson
会在GOPATH/bin下生成easyjson二进制可执行文件 go mod tidy通过扫描当前项目中的所有代码来添加未被记录的依赖至go.mod文件或从go.mod文件中删除不再被使用的依赖
二、包引入规则
包的声明 :
go文件的第一行声明 package xxx 在包声明的上面可写关于包的注释,包注释也可以专门写在doc.go里 包名跟目录名可以不同 同一个目录下,所有go文件的包名必须一致 **包的引用 **
可以直接使用同目录下其他go文件里的变量、函数、结构体 跨目录使用则需要变量前加入包名,并且引入包所在的目录
imoprt "go-course/package"
:go-course是model名,package是目录名mypackage.Add()
:mypackage是包名,它对应的目录是package 在import块里可以引用父目录,也可以引用子目录 引用关系不能构成一个环 在import的目录前面可以给包起一个别名
imoprt asd "go-course/package"
asd.Add()
三、init调用链
init函数
main函数是go程序的唯一入口,所以main函数只能存在一个;main函数必须位于main包中 在main函数执行之前会先执行init()函数 在一个目录,甚至一个go文件里,init()可以重复定义 引入其他包时,相应包里的init()函数也会在main()函数之前被调用 包引用而不用 :import _ "net/http/pprof"
在目录前加一个_,代码里却没有显式地使用这个包里的函数或变量,实际上是想执行这个包里的init()函数
四、可见性
可见性
以小写字母开头命名的函数、变量、结构体只能在本包内访问 以大写字母开头命名的函数、变量、结构体在其他包中也可以访问 如果结构体名字以大写字母开头,而其成员变量、成员方法以小写字母开头,则这样的成员只能在本包内访问 internal包 :
Go中命名为internal的package,可以被平级目录和上一级目录所访问,更上层的目录不能访问 c目录(internal的上一级目录)及其子孙目录之间可以任意import,但a目录和b目录不能import internal及其下属的所有目录
五、标准库
1 - 时间函数
func time_pro ( ) {
now := time. Now ( )
fmt. Println ( now. Unix ( ) )
fmt. Println ( now. UnixMilli ( ) )
fmt. Println ( now. UnixMicro ( ) )
fmt. Println ( now. UnixNano ( ) )
fmt. Println ( now. Weekday ( ) . String ( ) )
fmt. Println ( now. Hour ( ) )
fmt. Println ( now. Minute ( ) )
fmt. Println ( now. Second ( ) )
fmt. Println ( now. Month ( ) )
fmt. Println ( int ( now. Month ( ) ) )
fmt. Println ( now. Year ( ) )
fmt. Println ( now. YearDay ( ) )
fmt. Println ( now. Day ( ) )
fmt. Println ( now. Date ( ) )
}
func time_calc ( ) {
begin := time. Now ( )
for i := 1 ; i < 10000 ; i++ {
fmt. Printf ( "" )
}
fmt. Println ( "use some time" )
useTime1 := time. Since ( begin)
fmt. Println ( useTime1. Seconds ( ) )
fmt. Println ( useTime1. Nanoseconds ( ) )
fmt. Println ( "----------------------" )
end := time. Now ( )
useTime2 := end. Sub ( begin)
fmt. Println ( useTime2. Seconds ( ) )
fmt. Println ( useTime2. Nanoseconds ( ) )
fmt. Println ( "----------------------" )
dua := time. Duration ( 8 * time. Hour)
end_dua := begin. Add ( dua)
fmt. Println ( end_dua)
}
const (
TIME_FMT = "2006-01-02 15:04:05"
TIME_FMT1 = "2006-01-02"
TIME_FMT2 = "20060102"
)
func time_fmt ( ) {
begin := time. Now ( )
fmt. Println ( begin)
fmt. Println ( begin. Format ( TIME_FMT) )
fmt. Println ( begin. Format ( TIME_FMT1) )
fmt. Println ( begin. Format ( TIME_FMT2) )
}
func time_parse ( ) {
if t, err := time. Parse ( TIME_FMT1, "2022-02-18" ) ; err == nil {
fmt. Println ( t. Year ( ) )
fmt. Println ( t. Month ( ) )
fmt. Println ( t. Day ( ) )
}
loc, _ := time. LoadLocation ( "Asia/Shanghai" )
if t, err := time. ParseInLocation ( TIME_FMT1, "2022-02-18" , loc) ; err == nil {
fmt. Println ( t. Year ( ) )
fmt. Println ( t. Month ( ) )
fmt. Println ( t. Day ( ) )
}
}
func main ( ) {
tk := time. NewTicker ( 1 * time. Second)
defer tk. Stop ( )
for i := 0 ; i < 10 ; i++ {
<- tk. C
fmt. Printf ( "第[%d]次执行,[%d]\n" , i, time. Now ( ) . Unix ( ) )
}
tk. Stop ( )
}
定时执行 :time.NewTimer
、<-time.After
func main ( ) {
tm := time. NewTimer ( 3 * time. Second)
defer tm. Stop ( )
<- tm. C
fmt. Println ( time. Now ( ) . Unix ( ) )
<- time. After ( 3 * time. Second)
fmt. Println ( time. Now ( ) . Unix ( ) )
}
func main ( ) {
tm := time. NewTimer ( 3 * time. Second)
defer tm. Stop ( )
<- tm. C
fmt. Println ( time. Now ( ) . Unix ( ) )
for i := 0 ; i < 6 ; i++ {
tm. Reset ( 1 * time. Second)
<- tm. C
fmt. Println ( time. Now ( ) . Unix ( ) )
}
}
2 - 数学计算
func main ( ) {
fmt. Println ( math. E)
fmt. Println ( math. Pi)
fmt. Println ( math. MaxInt)
fmt. Println ( uint64 ( math. MaxUint64) )
}
func math_nan ( ) float64 {
if f, err := strconv. ParseFloat ( "12.56X8" , 64 ) ; err == nil {
return f
} else {
return math. NaN ( )
}
}
func main ( ) {
fmt. Println ( math. NaN ( ) )
rect := math_nan ( )
if math. IsNaN ( rect) {
fmt. Println ( "出错了" )
}
}
func main ( ) {
fmt. Println ( math. Ceil ( 1.1 ) )
fmt. Println ( math. Floor ( 1.9 ) )
fmt. Println ( math. Trunc ( 1.9 ) )
fmt. Println ( math. Modf ( 2.5 ) )
fmt. Println ( math. Abs ( - 2.6 ) )
fmt. Println ( math. Max ( 4 , 8 ) )
fmt. Println ( math. Min ( 4 , 8 ) )
fmt. Println ( math. Mod ( 6.5 , 3.5 ) )
fmt. Println ( math. Sqrt ( 9 ) )
fmt. Println ( math. Cbrt ( 9 ) )
fmt. Println ( math. Log ( 5 ) )
fmt. Println ( math. Log1p ( 4 ) )
fmt. Println ( math. Log10 ( 100 ) )
fmt. Println ( math. Log2 ( 8 ) )
fmt. Println ( math. Pow ( 3 , 2 ) )
fmt. Println ( math. Pow10 ( 2 ) )
fmt. Println ( math. Exp ( 2 ) )
fmt. Println ( math. Sin ( 1 ) )
fmt. Println ( math. Cos ( 1 ) )
fmt. Println ( math. Tan ( 1 ) )
fmt. Println ( math. Tanh ( 1 ) )
}
func math_rand ( ) {
rand. Seed ( time. Now ( ) . UnixMilli ( ) )
fmt. Println ( rand. Int ( ) )
fmt. Println ( rand. Float32 ( ) )
fmt. Println ( rand. Intn ( 100 ) )
fmt. Println ( rand. Perm ( 100 ) )
arr := [ ] int { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 }
rand. Shuffle ( len ( arr) , func ( i, j int ) {
arr[ i] , arr[ j] = arr[ j] , arr[ i]
} )
fmt. Println ( arr)
}
func math_rand ( ) {
source := rand. NewSource ( time. Now ( ) . UnixMicro ( ) )
rander := rand. New ( source)
for i := 0 ; i < 10 ; i++ {
fmt. Printf ( "%d " , rander. Intn ( 100 ) )
}
fmt. Println ( )
source. Seed ( time. Now ( ) . UnixMicro ( ) )
rander2 := rand. New ( source)
for i := 0 ; i < 10 ; i++ {
fmt. Printf ( "%d " , rander2. Intn ( 100 ) )
}
}
3 - I/O操作
输出格式 输出内容 %t 单词 true 或 false %b 表示为二进制 %d 表示为十进制 %e (=%.6e)有 6 位小数部分的科学计数法,如 -1234.456e+78 %f (=%.6f)有 6 位小数部分,如 123.456123 %g 根据实际情况采用 %e 或 %f 格式(获得更简洁、准确的输出) %s 直接输出字符串或者字节数组 %v 值的默认格式表示 %+v 类似 %v,但输出结构体时会添加字段名 %#v 值的 Go 语法表示 %Т 值的类型的 Go 语法表示
func std_io ( ) {
fmt. Println ( "please input two string" )
var s1 string
fmt. Scan ( & s1)
var s2 string
fmt. Scan ( & s2)
fmt. Printf ( "you input %s %s" , s1, s2)
var i int
fmt. Scan ( & i)
fmt. Printf ( "input int is %d" , i)
}
func read_file1 ( ) {
if file, err := os. Open ( "go.mod" ) ; err != nil {
fmt. Println ( err)
} else {
defer file. Close ( )
var buffer strings. Builder
for {
bs := make ( [ ] byte , 1024 )
if n, err := file. Read ( bs) ; err != nil {
fmt. Println ( err)
if err == io. EOF {
break
}
} else {
fmt. Printf ( "从文件中读出了%d个字节\n" , n)
buffer. WriteString ( string ( bs) )
}
}
fmt. Println ( buffer. String ( ) )
}
}
func read_file2 ( ) {
if file, err := os. Open ( "go.mod" ) ; err != nil {
fmt. Println ( err)
} else {
defer file. Close ( )
reader := bufio. NewReader ( file)
var i int
for {
if line, err := reader. ReadString ( '\n' ) ; err != nil {
fmt. Println ( err)
if err == io. EOF {
break
}
} else {
fmt. Printf ( "第%d行\n" , i)
fmt. Print ( line)
i++
}
}
}
}
func write_file1 ( ) {
if file, err := os. OpenFile ( "lala.txt" , os. O_CREATE| os. O_TRUNC| os. O_WRONLY, 0666 ) ; err != nil {
fmt. Println ( err)
} else {
defer file. Close ( )
file. Write ( [ ] byte ( "hello\n" ) )
}
}
func write_file2 ( ) {
if file, err := os. OpenFile ( "lala.txt" , os. O_CREATE| os. O_APPEND| os. O_WRONLY, 0666 ) ; err != nil {
fmt. Println ( err)
} else {
defer file. Close ( )
writer := bufio. NewWriter ( file)
writer. WriteString ( "hello" )
writer. WriteString ( "\n" )
writer. Flush ( )
}
}
**创建文件/目录 **:
os.Create(name string)//创建文件 os.Mkdir(name string, perm fs.FileMode)//创建目录 os.MkdirAll(path string, perm fs.FileMode)//增强版Mkdir,沿途的目录不存在时会一并创建 os.Rename(oldpath string, newpath string)//给文件或目录重命名,还可以实现move的功能 os.Remove(name string)//删除文件或目录,目录不为空时才能删除成功 os.RemoveAll(path string)//增强版Remove,所有子目录会递归删除
func main ( ) {
os. Remove ( "lala.txt" )
os. MkdirAll ( "p1/p2" , 0666 )
os. Create ( "p1/p2/lala.txt" )
os. RemoveAll ( "p1" )
os. Create ( "old.txt" )
os. Rename ( "old.txt" , "new.txt" )
}
func main ( ) {
file, _ := os. Open ( "go.mod" )
fmt. Println ( file. Name ( ) )
info, _ := file. Stat ( )
fmt. Println ( info. IsDir ( ) )
fmt. Println ( info. ModTime ( ) )
fmt. Println ( info. Mode ( ) )
fmt. Println ( info. Size ( ) )
fmt. Println ( info. Name ( ) )
}
func walk_dir ( path string ) error {
if fileInfos, err := ioutil. ReadDir ( path) ; err != nil {
return err
} else {
for _ , fileInfo := range fileInfos {
fmt. Println ( fileInfo. Name ( ) )
if fileInfo. IsDir ( ) {
if err := walk_dir ( filepath. Join ( path, fileInfo. Name ( ) ) ) ; err != nil {
return err
}
}
}
}
return nil
}
func main ( ) {
walk_dir ( "D:/Program Files" )
}
func logger ( ) {
if file, err := os. OpenFile ( "mage.log" , os. O_CREATE| os. O_APPEND| os. O_WRONLY, 0666 ) ; err != nil {
fmt. Println ( err)
} else {
defer file. Close ( )
logWriter := log. New ( file, "[BIZ_NAME]" , log. Ldate| log. Lmicroseconds)
logWriter. Println ( "hello" )
logWriter. Println ( "jack" )
logWriter. Println ( "tom" )
}
}
func sys_call ( ) {
cmd_path, err := exec. LookPath ( "netstat" )
if err != nil {
fmt. Println ( "os不支持 netstat命令" )
} else {
fmt. Println ( cmd_path)
cmd := exec. Command ( "netstat" , "-s" )
output, err := cmd. Output ( )
if err != nil {
fmt. Println ( err)
} else {
fmt. Print ( string ( output) )
}
}
cmd := exec. Command ( "calc" )
if err := cmd. Run ( ) ; err != nil {
fmt. Println ( err)
}
}
4 - 编码
compress :compress包下实现了zlib、bzip、gip、lzw等压缩算法
func compress ( ) {
fin, _ := os. Open ( "go.mod" )
fout, _ := os. OpenFile ( "go.mod.zlib" , os. O_CREATE| os. O_TRUNC| os. O_WRONLY, 0666 )
writer := zlib. NewWriter ( fout)
defer fin. Close ( )
defer fout. Close ( )
for {
bs := make ( [ ] byte , 10 )
n, err := fin. Read ( bs)
if err != nil {
if err == io. EOF {
break
} else {
fmt. Println ( err)
}
} else {
writer. Write ( bs[ : n] )
}
}
writer. Flush ( )
fin, _ = os. Open ( "go.mod.zlib" )
reader, _ := zlib. NewReader ( fin)
io. Copy ( os. Stdout, reader)
reader. Close ( )
fin. Close ( )
}
json :json是go标准库里自带的序列化工具,使用了反射,效率比较低
func test_json ( ) {
user := User{ "jack" , 18 }
if bs, err := json. Marshal ( user) ; err != nil {
fmt. Println ( err)
} else {
fmt. Println ( string ( bs) )
}
}
easyjson :
easyjson只针对预先定义好的json结构体对输入的json字符串进行纯字符串的截取,并将对应的json字段赋值给结构体 easyjson -all xxx.go 生成go文件中定义的结构体对应的解析 xxx.go所在的package不能是main
func test_easyjson ( ) {
user := stru. User{ Name: "jack" , Age: 18 }
if bs, err := easyjson. Marshal ( user) ; err != nil {
fmt. Println ( err)
} else {
fmt. Println ( string ( bs) )
}
}
base64 :
base64经常在http环境下用来传输较长的信息 任意byte数组都可以采用base64编码转为字符串,并且可以反解回byte数组 编码和解码的方法是公开、确定的, base64不属于加密算法
func test_base64 ( ) {
fin, _ := os. Open ( "C:/Users/nd/Desktop/Gopher.jpeg" )
bs := make ( [ ] byte , 1 << 20 )
n, _ := fin. Read ( bs)
str := base64. StdEncoding. EncodeToString ( bs[ : n] )
fmt. Println ( str)
bbb, _ := base64. StdEncoding. DecodeString ( str)
fout, _ := os. OpenFile ( "pic.png" , os. O_CREATE| os. O_TRUNC| os. O_WRONLY, 0666 )
fout. Write ( bbb)
fout. Close ( )
}