go语言的成神之路-筑基篇-对文件的操作
目录
一、对文件的读写
Reader 接口
Writer接口
copy接口
bufio的使用
ioutil库
二、cat命令
三、包
1. 包的声明
2. 导入包
3. 包的可见性
4. 包的初始化
5. 标准库包
6. 第三方包
7. 包的组织
8. 包的别名
9. 包的路径
10. 包的版本管理
四、go mod
1. 初始化一个新的模块
2. 依赖管理
3. 查看依赖关系
4. 下载依赖
5. 清理未使用的依赖
6. 替换依赖
7. 版本管理
8. 私有模块
9. 构建和测试
10. 示例
总结
一、对文件的读写
在 Go 语言中,io
包提供了基本的接口,用于 I/O 原语。它的主要目的是将这些原语抽象化,使得它们在不同的实现中可以通用。
Reader
接口
以下是一个对文件中内容读取的一个示例:
package mainimport ("fmt""io""os"
)func main() {// 打开文件 text.txt,如果打开失败,打印错误信息并返回file, err := os.Open("./text.txt")if err != nil {fmt.Println(err)return}// 确保文件在函数结束时关闭defer file.Close()// 定义一个长度为 128 的字节数组作为缓冲区var buf [128]byte// 存储文件内容的字节切片var content []bytefor {// 从文件中读取数据到缓冲区,n 表示读取的字节数n, err := file.Read(buf[:])// 如果到达文件末尾,跳出循环if err == io.EOF {break}// 如果读取过程中出现错误,打印错误信息并返回if err != nil {fmt.Println(err)return}// 将读取到的数据添加到 content 切片中content = append(content, buf[:n]...)}// 将字节切片转换为字符串并打印fmt.Println(string(content))
}
Writer接口
以下是写入文件的操作:
注:每次写入的时候原文件中的内容都会被覆盖。
// Writer接口的定义和实现
package mainimport ("fmt""os"
)func main() {// 打开文件 text.txt,如果文件不存在则创建,如果文件存在则清空内容file, err := os.Create("./text2.txt")if err != nil {fmt.Println(err)return}// 确保文件在函数结束时关闭defer file.Close()// 定义一个字符串str := "Hello,World!"// 将字符串转换为字节切片data := []byte(str)// 将字节切片写入文件_, err = file.Write(data)// 如果写入过程中出现错误,打印错误信息并返回if err != nil {fmt.Println(err)return}
}
写入一个 Hello,World!
写入一个”你好世界!“
可以看出原来文件中的文本被替换了。
copy接口
以下是复制文件的操作:
// io.Copy的使用
package mainimport ("fmt""io""os"
)func main() {// 打开文件 text.txt,如果文件不存在则创建,如果文件存在则清空内容begin, err := os.Open("./text2.txt")if err != nil {fmt.Println(err)return}// 确保文件在函数结束时关闭defer begin.Close()// 打开文件 text2.txt,如果文件不存在则创建,如果文件存在则清空内容end, err := os.Create("./text3.txt")if err != nil {fmt.Println(err)return}// 确保文件在函数结束时关闭defer end.Close()// 将文件 text.txt 的内容复制到文件 text2.txt 中_, err = io.Copy(end, begin)// 如果复制过程中出现错误,打印错误信息并返回if err != nil {fmt.Println(err)return}
}
begin中的内容会自动覆盖end中的内容。
bufio的使用
常见的方法如下:
// bufio的使用
package mainimport ("bufio""fmt""io""os"
)func wr() {// 参数2 是文件的打开方式,os.O_CREATE|os.O_WRONLY|os.O_APPEND 表示创建文件并以写入模式打开,文件不存在则创建,文件存在则在文件末尾追加内容// 参数3 是文件的权限,0666 表示文件所有者、组和其他用户都有读写权限// w写 r读 a追加 x执行file, err := os.OpenFile("./text.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)if err != nil {fmt.Println(err)return}defer file.Close()// 获取writer对象writer := bufio.NewWriter(file)writer.WriteString("hello bufio")// 刷新缓冲区writer.Flush()
}func rd() {file, err := os.Open("./text.txt")if err != nil {fmt.Println(err)return}defer file.Close()reader := bufio.NewReader(file)for {line, _, err := reader.ReadLine()if err != io.EOF {fmt.Println(err)break}if err != nil {fmt.Println(err)return}fmt.Println(string(line))}
}func main() {wr()
}
以这种方式进行读写不会覆盖原来的文件
读取文本文件的时候是按行读取的
ioutil库
// ioutil的使用
package mainimport ("fmt""io/ioutil"
)func wr() {err := ioutil.WriteFile("./text.txt", []byte("hello ioutil"), 0666)if err != nil {fmt.Println(err)return}
}func re() {content, err := ioutil.ReadFile("./text.txt")if err != nil {fmt.Println(err)return}fmt.Println(string(content))
}
func main() {wr()re()
}
这个工具库相对于其他的工具库更为简单。相应的函数已经被很好的打包完成了。
二、cat命令
package mainimport ("bufio""flag""fmt""io""os"
)// cat 函数接收一个 bufio.Reader 指针作为输入,用于读取文件或标准输入的内容
func cat(r *bufio.Reader) {// 开始一个无限循环,用于逐行读取数据for {// 从 bufio.Reader 中读取一行数据,直到遇到换行符 '\n',存储在 buf 中,并将可能的错误存储在 err 中buf, err := r.ReadBytes('\n')// 如果读取到文件末尾,打印错误信息并退出循环if err == io.EOF {fmt.Println(err)break}// 将读取到的一行数据输出到标准输出fmt.Fprintf(os.Stdout, "%s", buf)}
}func main() {// 解析命令行参数flag.Parse()if flag.NArg() == 0 {// 从标准输入读取数据并输出到标准输出cat(bufio.NewReader(os.Stdin))}// 依次处理每个文件for i := 0; i < flag.NArg(); i++ {// 打开文件f, err := os.Open(flag.Arg(i))if err!= nil {fmt.Fprintf(os.Stderr, "cat: %s: %s\n", flag.Arg(i), err)continue}// 读取文件内容并输出到标准输出cat(bufio.NewReader(f))// 关闭文件f.Close()}
}
上述代码中,cat
函数的主要功能是从 bufio.Reader
中逐行读取数据并输出到标准输出。在 for
循环中,使用 r.ReadBytes('\n')
方法读取一行数据,当遇到文件结束符 io.EOF
时,打印错误信息并退出循环,否则将读取的数据输出到标准输出。在 main
函数中,首先解析命令行参数,若没有命令行参数,则从标准输入读取数据;若有命令行参数,则依次打开文件,调用 cat
函数读取文件内容并输出,最后关闭文件。
注:在 cat
函数中,当遇到 io.EOF
时,打印错误信息可能不是最佳做法,因为 EOF
不是错误,而是文件结束的标志。可以考虑修改为不打印错误信息,仅退出循环。
如果文件中有内容就会打印出文件中的内容。
如果直接执行go run mian.go会打印输出用户输入的内容。
三、包
在 Go 语言中,包(package)是组织代码的一种方式,它可以将相关的函数、变量和类型组合在一起,以便于代码的管理、复用和维护。以下是关于 Go 语言包的一些重要信息:
1. 包的声明
在 Go 文件的开头,使用 package
关键字来声明包的名称。
package main
package main
是一个特殊的包,它表示该文件是一个可执行程序的入口点。- 对于其他包,可以使用其他名称,如
package utils
或package math
。
2. 导入包
使用 import
语句来导入其他包。
import ("fmt""os""github.com/yourusername/yourpackage"
)
- 导入标准库中的包,如
fmt
和os
。 - 导入第三方包,如
github.com/yourusername/yourpackage
。
3. 包的可见性
- 在 Go 中,标识符(函数、变量、类型)的名称首字母大小写决定了其可见性:
- 首字母大写的标识符是导出的,可以被其他包访问。
- 首字母小写的标识符是未导出的,只能在当前包内使用。
package mypackage// 导出的函数
func ExportedFunction() {
}// 未导出的函数
func unexportedFunction() {
}
在另一个包中,可以调用 mypackage.ExportedFunction()
,但不能调用 mypackage.unexportedFunction()
。
4. 包的初始化
包可以包含一个 init
函数,它会在包被导入时自动执行。
package mypackageimport "fmt"func init() {fmt.Println("Initializing mypackage")
}
- 一个包可以有多个
init
函数,它们会按照声明的顺序执行。
5. 标准库包
Go 标准库包含了许多有用的包,例如:
fmt
:格式化输入和输出。os
:提供操作系统功能,如文件操作、环境变量等。io
:提供基本的 I/O 操作接口。bufio
:提供缓冲的 I/O 操作。net
:提供网络编程功能。sync
:提供同步原语,如互斥锁、读写锁等。
6. 第三方包
可以使用 go get
命令来获取第三方包
比如在gin框架学习中引用的gin包
import "github.com/gin-gonic/gin"
7. 包的组织
- 通常,一个目录对应一个包。
- 包的名称应该与目录名称相同,除非使用
package main
。
8. 包的别名
可以为导入的包设置别名。
import (f "fmt"
)
- 这里将
fmt
包的别名设置为f
,可以使用f.Println()
来调用fmt.Println()
。
9. 包的路径
- 包的路径是其在文件系统或远程仓库中的位置。
- 对于标准库,路径是
std
包的一部分,如fmt
包的路径是std/fmt
。 - 对于第三方包,路径是其在远程仓库中的位置,如
github.com/gin-gonic/gin
。
10. 包的版本管理
- Go 1.11 及以后的版本支持模块(module),可以使用
go.mod
文件来管理依赖的版本。 - 例如,创建一个
go.mod
文件:
module mymodulego 1.14require github.com/gin-gonic/gin v1.7.4
这将确保使用 github.com/gin-gonic/gin
的 v1.7.4
版本。
以下是一个完整的示例,展示了包的使用:
package mainimport ("fmt""mypackage"
)func main() {// 使用标准库的 fmt 包fmt.Println("Hello, World!")// 使用自定义包 mypackagemypackage.ExportedFunction()
}
在这个示例中:
- 导入了
fmt
标准库包和mypackage
自定义包。 - 在
main
函数中,调用了fmt.Println()
和mypackage.ExportedFunction()
。
通过合理使用包,可以将代码组织得更加清晰、易于维护和复用,同时利用 Go 语言强大的标准库和丰富的第三方库资源。
四、go mod
go mod
是 Go 语言从 1.11 版本开始引入的模块管理工具,它允许开发者更好地管理项目的依赖关系,而不再依赖于 GOPATH
环境变量。
1. 初始化一个新的模块
使用 go mod init
命令来初始化一个新的模块。例如:
go mod init example.com/myproject
这将创建一个 go.mod
文件,内容如下:
module example.com/myprojectgo 1.14
module
后面的部分是模块的名称,通常是一个唯一的标识符,如域名加项目名。go
后面的部分是 Go 语言的版本。
2. 依赖管理
当你导入一个新的包时,go mod
会自动更新 go.mod
文件。例如:
package mainimport ("github.com/gin-gonic/gin"
)func main() {gin.Default()
}
运行 go build
或 go run
时,go mod
会自动更新 go.mod
文件,添加所需的依赖:
module example.com/myprojectgo 1.14require github.com/gin-gonic/gin v1.7.4
3. 查看依赖关系
使用 go list -m all
命令可以查看所有的依赖关系:
go list -m all
4. 下载依赖
使用 go mod download
命令可以下载所有的依赖:
go mod download
5. 清理未使用的依赖
使用 go mod tidy
命令可以清理未使用的依赖:
go mod tidy
6. 替换依赖
如果需要替换一个依赖,可以在 go.mod
文件中使用 replace
指令。例如:
replace github.com/oldpackage => github.com/newpackage v1.2.3
7. 版本管理
go mod
会自动选择依赖的最新版本,但可以使用require
指令指定版本。例如:
require github.com/gin-gonic/gin v1.7.4
- 可以使用
@
符号指定特定的版本,如v1.7.4
、v1.7.4+incompatible
或v1.7.4-pre
。
8. 私有模块
对于私有模块,可以使用 replace
指令或环境变量 GOPRIVATE
来管理。例如:
replace private.com/myproject => /path/to/local/project
9. 构建和测试
go build
和go test
命令会自动使用go.mod
中的依赖信息。
10. 示例
以下是一个完整的 go.mod
文件示例:
module example.com/myprojectgo 1.14require (github.com/gin-gonic/gin v1.7.4github.com/somepackage v1.2.3
)replace github.com/oldpackage => github.com/newpackage v1.2.3
总结
go mod init
初始化模块。go mod tidy
清理未使用的依赖。go mod download
下载依赖。go mod edit
编辑go.mod
文件。go list -m all
查看依赖。
使用 go mod
可以让 Go 项目的依赖管理更加灵活和方便,避免了 GOPATH
的限制,提高了项目的可维护性和可移植性。
相关文章:

go语言的成神之路-筑基篇-对文件的操作
目录 一、对文件的读写 Reader 接口 Writer接口 copy接口 bufio的使用 ioutil库 二、cat命令 三、包 1. 包的声明 2. 导入包 3. 包的可见性 4. 包的初始化 5. 标准库包 6. 第三方包 7. 包的组织 8. 包的别名 9. 包的路径 10. 包的版本管理 四、go mod 1. 初始…...

两道数据结构编程题
1.写出在顺序存储结构下将线性表逆转的算法,要求使用最少的附加空间。 解:输入:长度为n的线性表数组A(1:n) 输出:逆转后的长度为n的线性表数组A(1:n)。 C语言描述如下(其中ET为数据元素的类型):…...
【Qt】QDateTimeEdit控件实现清空(不保留默认时间/最小时间)
一、QDateTimeEdit控件 QDateTimeEdit 提供了一个用于编辑日期和时间的控件。用户可以通过键盘或使用上下箭头键来增加或减少日期和时间值。日期和时间的显示格式根据设置的格式显示,可以通过 setDisplayFormat() 方法来设置。 二、如何清空 我在使用的时候&#…...
12、字符串
1、字符串概念 字符串用来存储一组字符,因此需要字符数组来存。 C语言中字符串的表示 C语言里面字符串只能用字符数组来存 字符串要求这个数组的末尾必须至少有一个\0 char ch1[] {a,b,c}; // 不是字符串 char ch2[5] {h,e,l,l,o}; // 不是字符串 char…...

DPDK用户态协议栈-Tcp Posix API 1
和udp一样,我们需要实现和系统调用一样的接口来实现我们的tcp server。先来看看我们之前写的unix_tcp使用了哪些接口,这边我加上两个系统调用,分别是接收数据和发送数据。 #include <stdio.h> #include <arpa/inet.h> #include …...

【人工智能-科普】图神经网络(GNN):与传统神经网络的区别与优势
文章目录 图神经网络(GNN):与传统神经网络的区别与优势什么是图神经网络?图的基本概念GNN的工作原理GNN与传统神经网络的不同1. 数据结构的不同2. 信息传递方式的不同3. 模型的可扩展性4. 局部与全局信息的结合GNN的应用领域总结图神经网络(GNN):与传统神经网络的区别与…...
LabVIEW实现UDP通信
目录 1、UDP通信原理 2、硬件环境部署 3、云端环境部署 4、UDP通信函数 5、程序架构 6、前面板设计 7、程序框图设计 8、测试验证 本专栏以LabVIEW为开发平台,讲解物联网通信组网原理与开发方法,覆盖RS232、TCP、MQTT、蓝牙、Wi-Fi、NB-IoT等协议。 结合实际案例,展示如何利…...

[pdf,epub]228页《分析模式》漫谈合集01-45提供下载
《分析模式》漫谈合集01-45的pdf、epub文件提供下载。已上传至本号的CSDN资源。 如果CSDN资源下载有问题,可到umlchina.com/url/ap.html。 已排版成适合手机阅读,pdf的排版更好一些。 ★UMLChina为什么叒要翻译《分析模式》? ★[缝合故事]…...

Kafka的消费消息是如何传递的?
大家好,我是锋哥。今天分享关于【Kafka的消费消息是如何传递的?】面试题。希望对大家有帮助; Kafka的消费消息是如何传递的? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在Kafka中,消息的消费是通过消费…...
二分查找(Java实现)(1)
二分查找(Java实现)(1) leetcode 34.排序数组中查找元素第一个和最后一个位置 题目描述: 给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如…...

力扣103.二叉树的锯齿形层序遍历
题目描述 题目链接103. 二叉树的锯齿形层序遍历 给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。 示例 1ÿ…...

Search with Orama
1.前言 在不久之前,我把 DevNow 的搜索组件通过 Lunr 进行了重构,从前端角度实现了对文章内容的搜索,但是在使用体验上,感觉不是特别好,大概有如下几个原因: 社区的文章数量比较少,项目的 Com…...

一万台服务器用saltstack还是ansible?
一万台服务器用saltstack还是ansible? 选择使用 SaltStack 还是 Ansible 来管理一万台服务器,取决于几个关键因素,如性能、扩展性、易用性、配置管理需求和团队的熟悉度。以下是两者的对比分析,帮助你做出决策: SaltStack&…...
计算机类大厂实习春招秋招开发算法面试问答练习题
计算机类大厂实习春招秋招开发算法面试问答练习题 下面有十个非常重要且常问,面试者却注意不到的问题,我们一个个来看,一个个来学。 线程创建到删除过程中,底层是怎么实现的 1.线程创建 线程创建是线程生命周期的起点。在操作系统中,线程可以通过多种方式创建,但无论哪…...

【热门主题】000068 筑牢网络安全防线:守护数字世界的坚实堡垒
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 【热…...

RPC与HTTP调用模式的架构差异
RPC(Remote Procedure Call,远程过程调用)和 HTTP 调用是两种常见的通信模式,它们在架构上有以下一些主要差异: 协议层面 RPC:通常使用自定义的二进制协议,对数据进行高效的序列化和反序列化&am…...

计算机网络之传输层协议UDP
个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 计算机网络之传输层协议UDP 收录于专栏【计算机网络】 本专栏旨在分享学习计算机网络的一点学习笔记,欢迎大家在评论区交流讨论💌 目…...
Uniapp 微信小程序内打开web网页
技术栈:Uniapp Vue3 简介 实际业务中有时候会需要在本微信小程序内打开web页面,这时候可以封装一个路由页面专门用于此场景。 在路由跳转的时候携带路由参数,拼接上web url,接收页面进行参数接收即可。 实现 webview页面 新…...

阅读方法论
选择固有缺陷,选项是对比出来的...
373. 查找和最小的 K 对数字
参考的这个博客: https://zhuanlan.zhihu.com/p/457239781 然后看这个代码我想到了另外一种方法,就是一步一步往里加元组 ( i , j ) (i,j) (i,j),看代码就知道了,不过需要做一步去重,去重不能用 i n t [ ] int[] int…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...

Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...