Go 语言基础之常用包【flag、time、strconv、io】(1)https://developer.aliyun.com/article/1534276
3、strconv
Go 语言中 strconv 包实现了基本数据类型和其字符串表示的相互转换,主要有以下常用函数: Atoi()、Itoa()、parse系列、format系列、append系列。
3.1、string 转 int(Atoi)
为什么是 Atoi 而不是 Atos 呢?这是因为C语言中没有string类型而是用字符数组(array)表示字符串。
func main() { str := "100" num, _ := strconv.Atoi(str) fmt.Printf("%T,%v", num, num) // int,100 }
3.2、int 转 string(Itoa)
func main() { num := 100 str := strconv.Itoa(num) fmt.Printf("%T,%v", str, str) // string,100 }
3.3、Parse 系列
Parse类函数用于转换字符串为给定类型的值:ParseBool()、ParseFloat()、ParseInt()、ParseUint()。
b, _ := strconv.ParseBool("true") f, _ := strconv.ParseFloat("3.1415", 64) i, _ := strconv.ParseInt("-2", 10, 64) u, _ := strconv.ParseUint("2", 10, 64)
3.4、Format 系列
Format系列函数实现了将给定类型数据格式化为string类型数据的功能。
s1 := strconv.FormatBool(true) s2 := strconv.FormatFloat(3.1415, 'E', -1, 64) s3 := strconv.FormatInt(-2, 16) s4 := strconv.FormatUint(2, 16)
这里需要特别说明的是:
func FormatFloat(f float64, fmt byte, prec, bitSize int) string
- fmt 表示格式:‘f’(-ddd.dddd)、‘b’(-ddddp±ddd,指数为二进制)、’e’(-d.dddde±dd,十进制指数)、‘E’(-d.ddddE±dd,十进制指数)、‘g’(指数很大时用’e’格式,否则’f’格式)、‘G’(指数很大时用’E’格式,否则’f’格式)。
- prec 控制精度(排除指数部分):对’f’、’e’、‘E’,它表示小数点后的数字个数;对’g’、‘G’,它控制总的数字个数。如果prec 为-1,则代表使用最少数量的、但又必需的数字来表示f。
3.5、其它方法
func CanBackquote(s string) bool
表示返回字符串s是否可以不被修改的表示为一个单行的、没有空格和tab之外控制字符的反引号字符串。
4、文件操作
计算机中的文件是存储在外部介质(通常是磁盘)上的数据集合,文件分为文本文件和二进制文件(音频、视频)等。
4.1、文件的打开与关闭
// 返回文件对象指针和error对象 file, _ := os.Open("./main.go") defer file.Close()
4.2、普通方式读取文件
读取文件的方法源码:
func (f *File) Read(b []byte) (n int, err error)
其中,b 是一个用于存放文件读取进来的字节,相当于是一个缓冲区,可以重复使用。
func main() { file, _ := os.Open("./main.go") defer file.Close() // 开辟一个大小为128的字节切片用来存储文件 tmp := make([]byte, 128) n, err := file.Read(tmp) if err == io.EOF { fmt.Println("读取完毕") return } if err != nil { fmt.Println("读取失败") return } fmt.Printf("读取了%d字节的数据\n", n) fmt.Println(string(tmp[:n])) }
这种方式读取的缺点是我们并不能知道文件的大小,如果定义的缓冲区太大就浪费资源了,但是定义小了又读取不完整(因为只能读一次,不能循环利用),所以我们更多的是使用下面这种循环读取的方式:
func main() { file, _ := os.Open("./main.go") defer file.Close() var content []byte // 开辟一个大小为128的字节切片用来存储文件 tmp := make([]byte, 128) for { n, err := file.Read(tmp) if err == io.EOF { fmt.Println("读取完毕") break } if err != nil { fmt.Println("读取失败") return } content = append(content, tmp[:n]...) } fmt.Println(string(content)) }
这种方法每次都会从文件读取 128 字节数据,Read 方法的返回值是一个切片,所以需要使用 append 函数来汇总到 content 切片当中;从下一次读取,又会把上一次的结果覆盖掉,
4.3、使用 bufio 读取文件
bufio 是在 file 的基础上封装了一层API,支持更多的功能:
func main() { file, _ := os.Open("./main.go") defer file.Close() scanner := bufio.NewScanner(file) for scanner.Scan() { fmt.Println(scanner.Text()) } if err := scanner.Err(); err != nil { fmt.Println("读取失败", err) } }
4.4、使用 os.ReadFile 读取整个文件
os包(go1.16之前是 io.ioutil )的ReadFile方法能够读取完整的文件,只需要将文件名作为参数传入:
func main() { content, err := os.ReadFile("./main.go") if err != nil { fmt.Println("读取失败") return } fmt.Println(string(content)) }
4.5、文件写入操作
os.OpenFile()函数能够以指定模式打开文件,从而实现文件写入相关功能:
func OpenFile(name string, flag int, perm FileMode) (*File, error) { ... }
其中 name:要打开的文件名 flag:打开文件的模式。 模式有以下几种:
模式 | 含义 |
os.O_WRONLY | 只写 |
os.O_CREATE | 创建文件 |
os.O_RDONLY | 只读 |
os.O_RDWR | 读写 |
os.O_TRUNC | 清空 |
os.O_APPEND | 追加 |
4.5.1、Write 和 WriteString
func main() { // 0666是文件的权限设置,表示文件所有者、所属组和其他用户都有读写权限 file, err := os.OpenFile("./test.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666) if err != nil { fmt.Println("操作文件失败", err) return } defer file.Close() str := "Hello let's Go\n" file.Write([]byte(str)) file.WriteString("Hello Big Data") }
运行结果:
4.5.2、bufio.NewWriter
效果都是一样的,只不过是不同包下的方法:
func main() { // 0666是文件的权限设置,表示文件所有者、所属组和其他用户都有读写权限 file, err := os.OpenFile("./test.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666) if err != nil { fmt.Println("操作文件失败", err) return } defer file.Close() writer := bufio.NewWriter(file) for i := 0; i < 10; i++ { writer.WriteString("Hello let's Go\n") //将数据先写入缓存 } writer.Flush() // 将缓存中的内容写入文件 }
4.5.3、os.WriteFile
os 包(go1.16之前是 io.ioutil )下的 WriteFile 可以一次将一个byte切片内的数据全部写入文件当中。只不过不能指定写入模式,比如追加等。
func main() { str:="Hello let's Go" err := os.WriteFile("./test.txt", []byte(str), 0666) if err != nil { fmt.Println("写入失败") return } }