包的创建方式:
main 包 是应用程序的入口包, 其他的包不能使用
另外: 包内也可以嵌套定义包,
访问不同包下的函数需要导入包, 访问同一个包下不同文件的函数,不需要导入包。
点操作:
包名前加上. 那么可以不用写具体包名。
import .“fmt”
Println() 代替了 fmt.println()
但还是别这样用 ,当代码量大了,那么就会引起不必要的误会
包 起别名:
import p1 "package1" 那么p1就是package1的别名
导入 别的包下的模块的使用
Init 函数
Go文件中的init函数没有参数、没有返回值, 在main函数执行之前进行初始化。
如果一个Go文件中存在多个init函数, 那么将会按照定义的顺序执行初始化。
如果一个 package 下有多个go文件,而每个go文件中都有各自的init 函数 那么init函数的初始化执行顺序: 将所有go文件按照字符串 进行排序, 按照排序的的顺序执行init函数。
对于不同包: 如果存在多级依赖 :
则安照,递归的思想来处理init(package)
导入包 不能形成循环以来 ,否则 程序就无限递归下去了。
一个包可以被导入多次,但 init()函数只执行一次。
使用 包的注意事项
如果只是为了使用 包中的 init函数 , 那么只需要 在导入包名时 :在包名前 用 _ 导入这个包
今天发现Goland 的功能还挺强的 : 可以模拟虚拟机的使用, 用命令进行调试 和运行程序
看图片 下方: 我是不是在命令行进行运行程序啦? 挺美好的吧。
time 包
go 语言提供一个 强大的 go语言包, 可以实现各种函数调用
仅仅时间就具体道 皮秒 纳秒等 。
go语言的彩蛋: t1.Format(2006/1/2 15:04:05) 这个彩蛋 ,别的时间设置都是错误的, 据说是为了纪念Go语言的诞生时间。
time 包下提供各种强大的api ,需要注意的时 ,如果要Add Sub时间: 就需要转为time.duration(int) * Minute/Second 等才能使用
os 包 :大多是关于文件的API
os.Mkdir() 创建文件夹
os.MkdirAll () 递归创建文件夹
返回值有两个 ,一个是文件路径, 一个是错误类型
//Create 创建文件
package main
import (
"fmt"
"os"
)
func main(){
//创建绝对路径文件
//os.Create 文件不存在时 会创建文件, 文件存在时 会将其截断(置空)
file1,err := os.Create("/Users/mac/go/file_test/1.txt")
if err != nil{
fmt.Println(err)
}
fmt.Println(file1)// 打印地址
//创建绝对路径下的文件
FileName2 := "2.txt"
file2, err:= os.Create(FileName2)
if err != nil{
fmt.Println(err)
}
fmt.Println(file2)
}
FileName3 := "aa.txt"
file3,err := os.Open(FileName3)// Open 只读方式打开文件
if err != nil{
fmt.Println(err)
}
fmt.Println(file3)
//os.ModePerm 默认是 0777
//目标文件, 打开方式, 目标文件不存在时创建文件的权限
file4 ,err := os.OpenFile(FileName3, os.O_RDWR, os.ModePerm)
if err != nil{
fmt.Println(err)
return
}
fmt.Println(file4)
//关闭文件
file4.Close()
//删除文件
//os.Remove(" dest file's absolute path")
err1 :=os.Remove("/Users/mac/go/file_test/1.txt")
if err1 != nil{
fmt.Println(err1)
}
fmt.Println("删除目录成功")
//Remove 删除目录的前提是 : 该目录必须是一个空目录才可以删除
//RemoveALl() 递归删除一个目录下的所有文件和子目录
err2 := os.RemoveAll(" dest path")
if err2 != nil{
fmt.Println(err2)
}
fmt.Println(err2)
I/O 包
Reader接口 :
1 : os包下的 File 类实现了Read方法
2 IO 包下的 Reader 接口
FileName4 := "path"
file, err :=os.Open(FileName4) //Read 方式打开文件
if err != nil{
fmt.Println(err)
}
//关闭文件
defer file.Close()
DS := make([]byte,4,4)// 用切片接收数据
n ,err := file.Read(DS) // n: 读取到的长度
if err != nil{
fmt.Println(err)
}
fmt.Println(n)// 打印读取的数据
fmt.Println(string(DS))
//如果数据读完了|| 或者文件为空: 那么 err == io.EOF n==0
io包下的 read 方法有多种:
//写入数据 : 每次 会从文件的开头写入, 如果文件中已有数据,新写入的将会覆盖原有的数据
//想要追加写的话 需要在打开文件描述苻的时候指定 os.O_APPEND
FileName5 := "path5"
file, err = os.OpenFile(FileName5, os.O_RDWR|os.O_APPEND, os.ModePerm)
if err != nil{
fmt.Println(err)
}
//否则 ,打开文件成功
bs :=[]byte{'A','B','C','D'}
//将切片文件写入
n,err3 := file.Write(bs)
if err3 != nil{
fmt.Println(err3)
}
fmt.Println("写入了",n,"个字节数据")
//写出数据的一部分:
file.Write(bs[:3])//写入切片中的前三个
//直接写出字符串
n2,err :=file.WriteString("hello world")
println(n2," ",err)
n3, err :=file.Write([]byte("today"))//可以将 字符床做成一个切片
println(n3," ",err)
复制文件:
原理: 就是 读取一个文件 ,然后写入到另外一个文件中。 缓冲区我们使用切片
还可以使用 io提供的API
n, err := io.Copy(destFile, srcFile) // 结束err返回值为nil
值得注意的是 每个文件句柄都是需要判断文件是否打开成功。
ReadFile(filename string) ([]byte, error) 结束的时候 ,返回值error ==nil
下边是复制文件的两种方式 : 还有一种手动复制的,我就不实现了。
最简单的一种 : 我们自己手动实现一个 文件复制
第一种: io.Copy(dest, src)
第二种: ioutil.ReadFile() + ioutil.WriteFile() //底层用切片模拟缓存 ,一次性将文件复制到缓存中, 然后进行复制。因此:不建议大文件使用
func CopyFile1(srcFile,destFile string)(int64,error){
file1,err := os.Open(srcFile)
if err != nil{
return 0, err
}
//否则打开srcFile文件成功
file2,err := os.OpenFile(destFile,os.O_WRONLY|os.O_CREATE|os.O_APPEND,os.ModePerm )
if err != nil{
return 0,err
}
defer file2.Close()
defer file1.Close()
return io.Copy(file2,file1)
}
func CopyFile2(srcFile, destFile string)(int, error){
//打开文件
//内存(栈)中会自动建立一个缓冲区 ; 因此不适合较大文件的复制
bs,err := ioutil.ReadFile(srcFile)
if err != nil{
fmt.Println(err)
return 0,err
}
err = ioutil.WriteFile(destFile,bs,os.ModePerm)//或者写成0777一样的
if err != nil{
return 0, err
}
return len(bs),nil
}
另外IO包下还提供CopyN 和 CopyBuffer