Go语言基础 -- 常用库

0. 博客

https://www.cnblogs.com/luckzack/category/2342340.html

1. JSON操作

1.1 基本介绍

json(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成 key-val
json 易于机器解析和生成,并有效的提升网络传输效率,通常程序在网络传输时,会先将数据(机构提,map等)序列化成json字符串,到接收方得到json字符串时,再反序列化回复成原来的数据类型(结构体,map等)

1.2 JSON 格式

在js语言中,一切都是对象,因此,任何的数据类型都可以通过JSON来表示,例如字符串,数字,对象,数组,map,结构体等
JSON键值对是用来保存数据的一种方式,键值对组合中的键名写在前面,并用"" 双引号包裹,使用冒号: 分割,然后"值"

1.3 序列化

1.3.1 结构体序列化

package main

import (
	"encoding/json"
	"fmt"
)

type Monster struct {
	Name string
	Age int
	Birthday string
	Sal float64
	Skill string
}
func main() {
	monster := Monster{
		Name : "牛魔王",
		Age : 500,
		Birthday : "0253-11-11",
		Sal : 8000.0,
		Skill : "牛魔拳",
	}
        // 序列化函数
	data,err := json.Marshal(&monster)
	if err != nil{
		fmt.Println("序列化错误",err)
	}
	fmt.Printf("monster序列化后的内容%v",string(data))
}

1.3.2 map序列化

package main

import (
	"encoding/json"
	"fmt"
)

type Monster struct {
	Name string
	Age int
	Birthday string
	Sal float64
	Skill string
}
func main() {
	var a map[string]interface{}
	// 使用map需要先make
	a = make(map[string]interface{})
	a["name"] = "红孩儿"
	a["address"] = "火云洞"

	// 将map进行序列化
	data,err := json.Marshal(a)
	if err != nil{
		fmt.Println("序列化失败",err)
	}
	fmt.Println(string(data))
}

1.3.3 切片序列化

package main

import (
	"encoding/json"
	"fmt"
)

type Monster struct {
	Name string
	Age int
	Birthday string
	Sal float64
	Skill string
}
func main() {
	// map切片
	var z float64 = 1.24
	var a []map[string]interface{}
	var m1 map[string]interface{}
	// 使用map需要先make
	m1 = make(map[string]interface{})
	m1["name"] = "红孩儿"
	m1["address"] = [2]string{"火云洞","背景"}
	a = append(a,m1)

	// 将map进行序列化
	data,err := json.Marshal(a)
	data2,err := json.Marshal(z)
	if err != nil{
		fmt.Println("序列化失败",err)
	}
	fmt.Println(string(data))
	fmt.Printf("%v",string(data2))
}


1.3.4 基本数据类型序列化

同理

1.3.5 对字段首字母大小写的处理

序列化和反序列化时,键名的大小写可能会发生冲突,用json 的tag 解决

package main

import (
	"encoding/json"
	"fmt"
)

type Monster struct {
	Name string `json:"name"`  // 反射机制
	Age int `json:"age"`
	Birthday string `json:"birthday"`
	Sal float64 `json:"sal"`
	Skill string `json:"skill"`
}
func main() {
	monster := Monster{
		Name:"牛魔王",
		Age:500,
		Birthday:"023-1-2",
		Sal:8000.0,
		Skill:"牛魔拳",
	}

	// 将map进行序列化
	data,err := json.Marshal(monster)
	if err != nil{
		fmt.Println("序列化失败",err)
	}
	fmt.Println(string(data))
}

1.4 反序列化

package main

import (
	"encoding/json"
	"fmt"
)

type Monster struct {
	Name string `json:"name"`
	Age int `json:"age"`
	Birthday string `json:"birthday"`
	Sal float64 `json:"sal"`
	Skill string `json:"skill"`
}
func main() {
	monster := Monster{
		Name:"牛魔王",
		Age:500,
		Birthday:"023-1-2",
		Sal:8000.0,
		Skill:"牛魔拳",
	}
	// 将map进行序列化
	data,err := json.Marshal(monster)
	if err != nil{
		fmt.Println("序列化失败",err)
	}
	dataStr := string(data)
	fmt.Println(dataStr)
        // 反序列化时,对于需要make的类型,内部源码已经make过了
	err2 := json.Unmarshal([]byte(dataStr),&monster)
	if err2 != nil{
		fmt.Println("反序列化失败",err2)
	}
	fmt.Println(monster)
}

1.5 注意事项

  1. 在反序列化一个JSON 字符串时,要确保反序列化之后的数据类型和原来序列化前的数据类型(里面的字段)保持一致

2. 文件操作

2.1 文件基本介绍

文件是数据源(保存数据的地方),文件在程序中是以流的形式来操作的

2.2 读取文件Open()

2.2.1 带缓冲区一行一行读取

读取文件的内容并打印在终端(带缓冲区的方式)

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func main() {
	
    // 1. 打开文件
	file, err := os.Open("D:\\python\\PythonProject\\demo1\\manage.py")
	
    // 2. 判断是否读取文件发生错误
    if err != nil {
		fmt.Println("打开文件失败")
	}

    // 3. 当函数退出时,要及时关闭file,否则会有内存泄漏 
	defer file.Close()
	
    // 4. 创建一个 *reader,带缓冲区的,默认缓冲区为4096字节
	reader := bufio.NewReader(file)

    // 5. 循环读取文件的内容
	for {
        // 5.1 读取文件内容,以读到\n结束,即一行数据
		str, err := reader.ReadString('\n')
        
        // 5.2 io.EOF 表示是文件的末尾
		if err == io.EOF {
			break
		}
		fmt.Println(str)
	}
}

2.2.2 一次性读取全部

使用ioutil一次性将整个文件读入到内存中),这种方式适用于文件不大的情况

package main

import (
	"fmt"
	"io/ioutil"
)

func main() {

	// 内部源码将open和close 都已经做了
	file, err := ioutil.ReadFile("D:\\python\\PythonProject\\demo1\\manage.py")
	if err != nil {
		fmt.Println("打开文件失败")
	}

	fmt.Println(string(file))
}

2.3 写文件OpenFile()

写文件操作应用实例

func OpenFile(name string,flag int,perm FileMode)(file *File,err error)

os.OpenFile是一个更一般性的文件打开函数,它会使用指定的选项(如O_RDONLY等),指定的模式(如O666等)打开指定名称的文件,如果操作成功,返回的文件对象可用于I.O,如果出错,错误底层类型是*PathError

2.3.1 打开文件的模式常量

可以以 | 符号组合使用

const (
    O_RDONLY int = syscall.O_RDONLY // 只读模式打开文件
    O_WRONLY int = syscall.O_WRONLY // 只写模式打开文件
    O_RDWR   int = syscall.O_RDWR   // 读写模式打开文件
   
    O_APPEND int = syscall.O_APPEND // 写操作时将数据附加到文件尾部
    O_CREATE int = syscall.O_CREAT  // 如果不存在将创建一个新文件
    O_EXCL   int = syscall.O_EXCL   // 和O_CREATE配合使用,文件必须不存在
    O_SYNC   int = syscall.O_SYNC   // 打开文件用于同步I/O
    O_TRUNC  int = syscall.O_TRUNC  // 如果可能,打开时清空文件
)

3.3.2 FileMode 参数解析

Linux.Unix操作系统下才可以使用(权限控制 r-->4,w-->2,x-->1)

const (
    // 单字符是被String方法用于格式化的属性缩写。
    ModeDir        FileMode = 1 << (32 - 1 - iota) // d: 目录
    ModeAppend                                     // a: 只能写入,且只能写入到末尾
    ModeExclusive                                  // l: 用于执行
    ModeTemporary                                  // T: 临时文件(非备份文件)
    ModeSymlink                                    // L: 符号链接(不是快捷方式文件)
    ModeDevice                                     // D: 设备
    ModeNamedPipe                                  // p: 命名管道(FIFO)
    ModeSocket                                     // S: Unix域socket
    ModeSetuid                                     // u: 表示文件具有其创建者用户id权限
    ModeSetgid                                     // g: 表示文件具有其创建者组id的权限
    ModeCharDevice                                 // c: 字符设备,需已设置ModeDevice
    ModeSticky                                     // t: 只有root/创建者能删除/移动文件
    // 覆盖所有类型位(用于通过&获取类型位),对普通文件,所有这些位都不应被设置
    ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice
    ModePerm FileMode = 0777 // 覆盖所有Unix权限位(用于通过&获取类型位)
)

2.3.3 带缓冲区写文件示例

创建一个新文件,写入5句"hello,Gardon"

package main

import (
	"bufio"
	"fmt"
	"os"
	"syscall"
)

func main() {
	// 1. 打开文件(打开模式,权限)
	file, err := os.OpenFile("D:\\hello.txt", syscall.O_WRONLY|syscall.O_CREAT, 0666)
	if err != nil {
		fmt.Println("打开文件失败")
	}

	// 2. 延时关闭文件资源
	defer file.Close()

	// 3. 创建写的buffer
	writer := bufio.NewWriter(file)

	// 4. 写入缓冲区
	for i := 0; i < 5; i++ {
		writer.WriteString("hello,Gardon\n")
	}

	// 5. 将缓冲区的内容写入文件中
	writer.Flush()
	fmt.Println("写入成功")
}

打开一个存在的文件,将原来的内容覆盖成新的内容10句"你好,北京"

package main

import (
	"bufio"
	"fmt"
	"os"
	"syscall"
)

func main() {
	// 1. 打开文件(打开模式,权限)
	file, err := os.OpenFile("D:\\hello.txt", syscall.O_WRONLY, 0666)
	if err != nil {
		fmt.Println("打开文件失败")
	}

	// 2. 延时关闭文件资源
	defer file.Close()

	// 3. 创建写的buffer
	writer := bufio.NewWriter(file)

	// 4. 写入缓冲区
	for i := 0; i < 5; i++ {
		writer.WriteString("你好,北京\n")
	}
	// 5. 将缓冲区的内容写入文件中
	writer.Flush()
	fmt.Println("写入成功")
}

打开一个存在的文件,在原来的内容追加内容"ABCI ENGLISH"

package main

import (
	"bufio"
	"fmt"
	"os"
	"syscall"
)

func main() {
	// 1. 打开文件(打开模式,权限)
	file, err := os.OpenFile("D:\\hello.txt", syscall.O_APPEND, 0666)
	if err != nil {
		fmt.Println("打开文件失败")
	}

	// 2. 延时关闭文件资源
	defer file.Close()

	// 3. 创建写的buffer
	writer := bufio.NewWriter(file)

	// 4. 写入缓冲区
	writer.WriteString("ABCI ENGLISH\n")

	// 5. 将缓冲区的内容写入文件中
	writer.Flush()
	fmt.Println("写入成功")
}

打开一个存在的文件,将原来的内容读出显示在终端,并且追加5句"hello,北京"

package main

import (
	"bufio"
	"fmt"
	"os"
	"syscall"
)

func main() {
	// 1. 打开文件(打开模式,权限)
	file, err := os.OpenFile("D:\\hello.txt", syscall.O_RDWR|syscall.O_APPEND, 0666)
	if err != nil {
		fmt.Println("打开文件失败")
	}

	// 2. 延时关闭文件资源
	defer file.Close()

	// 3. 创建写的buffer
	writer := bufio.NewWriter(file)

	// 4. 写入缓冲区
	for i := 0; i < 5; i++ {
		writer.WriteString("ABCI ENGLISH\n")
	}
	// 5. 将缓冲区的内容写入文件中
	writer.Flush()
	fmt.Println("写入成功")
}

将一个文件的内容写入到另一个文件中,两个文件都已经存在

package main

import (
	"fmt"
	"io/ioutil"
)

func main() {
	file1path := "D:\\hello.txt"
	file2path := "D:\\beijing.txt"

	// 1. 将file1的数据流读到内存中
	data, err := ioutil.ReadFile(file1path)
	if err != nil {
		fmt.Println("文件读取错误", err)
		return
	}

	// 2. 将内存中的数据直接写入
	writeErr := ioutil.WriteFile(file2path, data, 0666)
	if writeErr != nil {
		fmt.Println("写文件错误", err)
		return
	} else {
		fmt.Println("写入文件成功")
	}
}

2.4 常用函数

2.4.1 判断文件是否存在

golang 判断文件或文件夹是否存在的方法为使用os.stat()函数返回的错误值进行判断:

  1. 如果返回的错误为nil,说明文件或者文件夹已存在
  2. 如果返回的错误类型使用os.IsNotExist()判断为true,说明文件或文件夹不存在
  3. 如果返回的错误为其他类型,则不确定是否存在
fileinfo,err := os.Stat(path)
if err == nil{
    fmt.Println("文件已存在")
}
if os.IsNotExist(err){
    fmt.Println("文件不存在")
}
fmt.Println("不确定文件存不存在")

2.4.2 拷贝文件

将一张图片/MP4/MP3 拷贝到另一个文件中,io包中的Copy方法

func Copy(dst Writer, src Reader) (written int64, err error)

// 将src的数据拷贝到dst,直到在src上到达EOF或发生错误。返回拷贝的字节数和遇到的第一个错误。

// 对成功的调用,返回值err为nil而非EOF,因为Copy定义为从src读取直到EOF,它不会将读取到EOF视为应报告的错误。
// 如果src实现了WriterTo接口,本函数会调用src.WriteTo(dst)进行拷贝;
// 否则如果dst实现了ReaderFrom接口,本函数会调用dst.ReadFrom(src)进行拷贝。

示例:

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"syscall"
)

func main() {
	file1path := "C:\\Users\\Administrator\\Desktop\\1.jpg"
	file2path := "d:/2.jpg"
	
    // 1. 将文件读到内存中
	f, err := os.Open(file1path)
	if err != nil {
		fmt.Println("打开文件错误", err)
		return
	}
    
    // 2. 延时关闭文件1资源
    defer f.Close()
    
    // 3. 创建buffer 
	reder := bufio.NewReader(f)
	
    // 4. 打开另一个文件
	file, err := os.OpenFile(file2path, syscall.O_WRONLY|syscall.O_CREAT, 0666)
	if err != nil {
		fmt.Println("写文件错误", err)
		return
	}
    // 5. 延时关闭文件2资源
    defer reder.Close()
    
     // 6. 创建buffer 
	Writer := bufio.NewWriter(file)

    // 7. 将文件1的内容拷贝到文件2中
	written,err := io.Copy(Writer, reder)
	if err != nil {
		fmt.Println("拷贝文件错误", err)
	}
	fmt.Println(written)
}

2.4.3 统计文件中字符

统计一个文件中含有的英文,数字,空格,以及其他字符数量

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

// 保存结果
type result struct {
	Chcount int
	Nucount int
	Spacecount int
	othercount int
}

func main() {
	file1path := "D:\\ceshi\\main.py"

	f,err := os.Open(file1path)
	if err != nil{
		fmt.Println("文件打开错误",err)
		return
	}
	reder := bufio.NewReader(f)
	var count result
	for {
		str,err := reder.ReadString('\n')
		if err == io.EOF{
			return
		}
		// 遍历str 进行统计
		str2 := []rune(str)
		for _,v := range str2{
			switch {
				case v >= 'a' && v <= 'z':
					fallthrough
				case v >= 'A' && v <= 'Z':
					count.Chcount++
				case v == ' ' || v == '\t':
					count.Spacecount++
				case v <= '9' && v <= '0':
					count.Spacecount++
				default:
					count.othercount++
			}
		}
	}
}


3. 日期操作

3.1 包导入

import time

3.2 获取当前时间

time.Now()   // 类型为time.Time

3.3 获取年月日等等日期信息

now := time.Now()

now.Year()  
now.Month()  // May  , 转成对应的数字,可以直接用int(now.Month())强转
now.Day()
now.Hour()
now.Minute()
now.Second()

3.4 格式化日期和时间

now := time.Now()

方式一:使用Printf 或者 Sprintf

fmt.Printf("%02d-%02d-%02d %02d:%02d:%02d",now.Year(),int(now.Month()),now.Day(),now.Hour(),now.Minute(),now.Second())

string = fmt.Sprintf("%02d-%02d-%02d %02d:%02d:%02d",now.Year(),int(now.Month()),now.Day(),now.Hour(),now.Minute(),now.Second())   //返回给变量然后存入数据库
fmt.Println(string)

方式二:Format()

fmt.Printf(now.Format("2006-01-02 15:04:05"))  // 2006/01/02 15:04:05时间格式是固定的

3.5 时间的常量

Nanosecond Duration=1 //纳秒
Microsecond  == 1000 * Nanosecond  // 微妙
Millisecond  == 1000 * Microsecond  // 毫秒
Second       == 1000 * Millisecond  // 秒
Minute       == 60 * second // 分钟
Hour         == 60 * Minute // 小时
想得到100毫秒   100 * Millisecond

3.6 获取当前时间戳 (可以获取随机的数字)

Unix 时间戳  -- 秒数
Unixnano  时间戳  -- 纳秒数


now := time.Now()
now.Unix()
now.Unixnano()
posted @ 2023-12-01 13:53  河图s  阅读(23)  评论(0)    收藏  举报