目录
- 一、用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()
}