GO语言基础(下)

go语言基础 下


1、常用包

1、strings

strings包内提供了一系列对字符串操作的函数

package stringsdemo

import (
	"fmt"
	"strings"
)

func Test() {
	str := "nihaoaaaaa heiheiwoshi SB"

	fmt.Println(str[0])

	//判断某个字符是由包含了指定的内容
	fmt.Println(strings.Contains(str, "hao"))

	//判断某个字符串是否包含了多个字符串的另一个
	fmt.Println(strings.ContainsAny(str, "ca"))

	//统计这个字符在指定字符串中出现的数量
	fmt.Println(strings.Count(str, "aa"))

	str2 := []string{"a", "b", "c", "d", "e", "f", "g"}
	//字符合并,sep为连接的分隔符
	str3 := strings.Join(str2, "-")

	//用sep切分字符串
	str4 := strings.Split(str3, "-")
	fmt.Println(str4)
		
}

还有很多,可以点进strings包的源码进行查看。 

2、strconv

strconv字符串转换包

package stringsdemo

import (
	"fmt"
	"strconv"
)

func Test() {

	//字符串与bool类型的转化
	//字符串转化为bool值(解析:bool)
	//bool转为字符串(格式化:format)
	a1 := "false"
	b1, err := strconv.ParseBool(a1)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("%T,%t\n", b1, b1)

	a2 := strconv.FormatBool(b1)
	fmt.Printf("%T,%s\n", a2, a2)

	//整数与字符串之间的转化
	a3 := "10"
	b2, _ := strconv.Atoi(a3)
	fmt.Printf("%T,%d\n", b2, b2)
	//参数——原始字符串——进制(10进制)——整数类型、int64,int32..
	b3, _ := strconv.ParseInt(a3, 10, 64)
	fmt.Printf("%T,%d\n", b3, b3)

	b4 := strconv.FormatInt(b3, 10)
	fmt.Printf("%T,%s\n", b4, b4)
	b5 := strconv.Itoa(b2)
	fmt.Printf("%T,%s\n", b5, b5)

}

3、time

一些跟时间相关的函数和常量

package stringsdemo

import (
	"fmt"
	"time"
)

// 获取当前时间 now
func time1() {
	// 返回值为Time结构体 : 常量:日月年时分秒 周日-周六 方法:获取常量,计算。
	now := time.Now()

	year := now.Year()
	month := now.Month()
	day := now.Day()
	hour := now.Hour()
	minute := now.Minute()
	second := now.Second()
	// 2023-2-23 20:40:31

	fmt.Printf("%d-%d-%d %d:%d:%d\n", year, month, day, hour, minute, second)

}

func time2() {
	now := time.Now()
	// 时间格式化 2023-02-23 20:43:49
	// 固定的:"2006-01-02 15:04:05"
	fmt.Println(now.Format("2006-01-02 15:04:05"))    // 24小时制
	fmt.Println(now.Format("2006-01-02 03:04:05 PM")) // 12小时制
}

// 将字符串格式化为Time对象
func time3() {
	loc, err := time.LoadLocation("Asia/Shanghai")
	if err != nil {
		fmt.Println(err)
		return
	}
	// 将字符串解析为时间 Time
	timeStr := "2023-02-23 20:53:08"
	// layout 格式 时间字符串  时区位置 , 需要和前端传递的格式进行匹配
	timeObj, _ := time.ParseInLocation("2006-01-02 15:04:05", timeStr, loc)
	fmt.Println(timeObj)
}

// 时间戳:更多时候和随机数结合
func time4() {
	now := time.Now()
	timestamp1 := now.Unix()     // 时间戳
	timestamp2 := now.UnixNano() // 纳秒的时间数

	fmt.Println(timestamp1)
	fmt.Println(timestamp2)

	// 通过 Unix 转换time对象
	timeObj := time.Unix(timestamp1, 0) // 返回time对象
	year := timeObj.Year()
	month := timeObj.Month()
	day := timeObj.Day()
	hour := timeObj.Hour()
	minute := timeObj.Minute()
	second := timeObj.Second()
	fmt.Printf("%d-%d-%d %d:%d:%d\n", year, month, day, hour, minute, second)
}

4、rand

使用math/rand包生成随机数

package main

import (
	"fmt"
	"math/rand"
	"time"
)

// random随机数- math/rand
func main() {
	// 获取一个随机数
	num1 := rand.Int()
	fmt.Println("num1:", num1)
	// 随机需要一个随机数的种子,如果种子一样,那么结果一致
	// n范围(0-n)
	num2 := rand.Intn(100)
	fmt.Println("num2:", num2) // 7

	// 需要一个随时都在发生变化的量 时间戳
	timestamp := time.Now().Unix()
	// 设置随机数种子, 使用时间戳
	// 种子只需要设置一次即可。
	rand.Seed(timestamp) // 每次执行都不同
		fmt.Println(num1)
	}

}

GO语言现在貌似不在需要初始化随机数种子

2、I/O操作

文件就是存储在磁盘上的数据,文件分为二进制文件和文本文件

go中操作文件是通过os操作系统包,里面封装了底层的文件描述符和相关信息fileInfo,同时封装了Read和Write方法。

package main

import (
	"fmt"
	"os"
)

func main() {
	//使用Stat函数返回文件信息,里面为文件的路径
	fileInfo, _ := os.Stat("D:\\Goland\\library\\src\\HelloWorld\\hello_world.go")

	fmt.Println(fileInfo.Name())    //文件名
	fmt.Println(fileInfo.Size())    //文件大小
	fmt.Println(fileInfo.ModTime()) //修改时间
	fmt.Println(fileInfo.IsDir())   //是否是文件夹
	fmt.Println(fileInfo.Mode())    //权限
}

Stat返回类型为FileInfo类型 

1、创建目录文件

package main

import (
	"fmt"
	"os"
)

func main() {
	//---------------------------创建目录--------------------------------
	//创建文件夹,只能创建一层文件夹,os.ModePerm为权限0777
	err1 := os.Mkdir("D:\\Goland\\library\\src\\HelloWorld\\hello", os.ModePerm)
	if err1 != nil {
		panic(err1)
	}
	
	//移除文件夹,通过此方法只能删除单个空文件夹
	err2 := os.Remove("D:\\Goland\\library\\src\\HelloWorld\\hello")
	if err2 != nil {
		panic(err2)
	}
	
	//递归创建多层文件夹
	err3 := os.MkdirAll("D:\\Goland\\library\\src\\HelloWorld\\hello\\aa\\bb", os.ModePerm)
	if err3 != nil {
		panic(err3)
	}
	
	//递归删除多层文件夹,删除这个目录下的所有东西,强制删除
	err4 := os.RemoveAll("D:\\Goland\\library\\src\\HelloWorld\\hello\\aa\\bb")
	if err4 != nil {
		panic(err4)
	}

	//---------------------------创建文件--------------------------------
	//os.Create()若存在则打开(即返回操作指针,可以对文件进行操作),不存在则创建
	file, _ := os.Create("a.go") //相对路径
	fmt.Println(file)

	//删除文件
	os.Remove("a.go")
}

2、打开文件

package main

import (
	"fmt"
	"os"
)

func main() {
	//打开文件,返回文件指针
	file1, err1 := os.Open("hei.txt")
	if err1 != nil {
		fmt.Println(err1)
		return
	}
	fmt.Println(file1)

	//打开文件的时候,选则打开方式,O_RDWR可读可写
	//第三个参数的作用是如果文件不存在创建参数时权限的选项
	file2, err2 := os.OpenFile("hei.txt", os.O_RDWR|os.O_CREATE, os.ModePerm)
	if err2 != nil {
		fmt.Println(err2)
	}
	fmt.Println(file2)

	//可以同时打开,因为打开方式不同,即两个文件指针,指向同一个文件

}

3、读取文件

package main

import (
	"fmt"
	"os"
)

func main() {
	//打开文件
	file1, err1 := os.Open("hei.txt")
	if err1 != nil {
		fmt.Println(err1)
		return
	}
	//操作关闭后,关闭文件
	defer file1.Close()

	//创建容器切片
	buf := make([]byte, 1024)
	//将文件内的内容读取到buf中,返回值为文件长度,
	//err为错误,若出现EOF错误,则代表文件读取完毕
	size, err2 := file1.Read(buf)
	if err2 != nil {
		fmt.Println(err2)
		return
	}
	if size != 0 {
		fmt.Println(string(buf[:size]))
	}

}

 

4、写入文件 

package main

import (
	"fmt"
	"os"
)

func main() {
	//打开文件,建立连接
	filename := "hei.txt"
	//若不加os.O_APPEND,则光标会在最前面,从头写,会覆盖原内容
	//通过os.O_APPEND,则向文件后面追加内容
	file, _ := os.OpenFile(filename, os.O_RDWR|os.O_APPEND, os.ModePerm)
	defer file.Close()

	//写文件,Write方法写入内容为字节切片
	bs := []byte{65, 66, 67, 68, 69}
	n, err := file.Write(bs)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(n)

	//写入字符串
	n, err = file.WriteString("hello world")
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(n)
}

5、seeker

seeker是一个接口类,里面实现了唯一Seek函数,用于确定光标的位置,以便确定下次读取或写入开始的位置。

Seek函数有两个参数,即offset和whence,先解释第二个参数,该参数有三个值,如下:

 

SeekStart:文件的起始位置,SeekCurrent:文件当前位置,SeekEnd:文件结尾位置

offset:为偏移量

要想移动文件光标位置,首先要确定的是从哪里开始,因此要有第二个参数,再通过偏移量,即可确定光标位置。

package main

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

func main() {
   // 读取文件
   file, _ := os.OpenFile("D:\\Goland\\library\\src\\HelloWorld",
      os.O_RDWR, os.ModePerm)
   // defer close
   defer file.Close()

   // 测试seek
   // 相对开始位置。io.SeekStart
   // 相对于文件末尾, io.SeekEnd
   file.Seek(2, io.SeekStart)
   buf := []byte{0}
   file.Read(buf)

   fmt.Println(string(buf))

   // 相对于当前位置
   file.Seek(3, io.SeekCurrent)
   file.Read(buf)

   fmt.Println(string(buf))

   // 在结尾追加内容
   file.Seek(0, io.SeekEnd)
   file.WriteString("xixixxixi")
}

6、文件操作案例

1、断点续传

传续到一半发生错误,传输一半的文件,下次能够从中断的位置进行传输

package main

import (
	"fmt"
	"io"
	"os"
	"strconv"
	"time"
)

func main() {

	io.Seeker()
	srcFile := "C:\\Users\\zhangyahui\\Desktop\\client\\wallhaven-9mdkv1.jpg"
	dstFile := "D:\\Goland\\library\\src\\HelloWorld\\server\\wh.jpg"
	tempFile := "D:\\Goland\\library\\src\\HelloWorld\\temp.txt"

	file1, _ := os.Open(srcFile)
	defer file1.Close()

	file2, _ := os.OpenFile(dstFile, os.O_RDWR|os.O_CREATE, os.ModePerm)
	defer file2.Close()

	file3, _ := os.OpenFile(tempFile, os.O_RDWR|os.O_CREATE, os.ModePerm)

	//1、读取temp.txt
	//设定缓冲区字节切片大小
	buf := make([]byte, 1024)
	//读取file3.txt获取偏移量
	file3.Seek(0, io.SeekStart)
	//将偏移量存入buf中
	n, _ := file3.Read(buf)

	//此时buf中的偏移量为字节类型,先转乘string,再转成int类型
	count, _ := strconv.ParseInt(string(buf[:n]), 10, 64)

	//2、设置file1,file2的偏移量
	file1.Seek(count, io.SeekStart)
	file2.Seek(count, io.SeekStart)

	//开始读写
	bufData := make([]byte, 1024)

	total := int(count)

	for {
		readNum, err := file1.Read(bufData)
		if err == io.EOF {
			fmt.Println("chuanshuwanbi")

			time.Sleep(time.Second * 3)

			file3.Close()
			os.Remove(tempFile)
			break
		}

		writeNum, _ := file2.Write(bufData[:readNum])

		total += writeNum

		file3.Seek(0, io.SeekStart)
		file3.WriteString(strconv.Itoa(total))
	}
}

2、遍历文件夹

package main

import (
	"fmt"
	"log"
	"os"
)

func main() {
	dir := "D:\\Goland\\library\\src\\HelloWorld"
	tree(dir)
}

func tree(dir string) {
	fileInfos, err := os.ReadDir(dir)
	if err != nil {
		log.Println(err)
	}
	for _, fileInfo := range fileInfos {
		// 文件夹中文件的全路径展示
		filename := dir + "\\" + fileInfo.Name()
		fmt.Println(fileInfo.Name())
		// 如果是文件夹,再次遍历
		if fileInfo.IsDir() {
            //递归遍历
			tree(filename)
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值