文章目录
- 1 文件处理
- 1.1 打开和关闭文件
- 1.2 读取文件
- 1.2.1 简单示例
- 1.2.2 中文乱码
- 1.2.2.1 bufio
- 1.2.2.2 ioutil
- 1.3 写入文件
- 1.3.1 Write 和 WriteString
- 1.3.2 fmt.Fprintln
- 1.3.2.1 写入文件
- 1.3.2.2 写入标准输出
- 1.3.3 bufio.NewWriter
- 1.3.4 ioutil.WriteFile
- 2 TCP&UDP
- 2.1 TCP
- 2.1.1 服务端
- 2.1.2 客户端配置
- 2.2 UDP
- 2.2.1 服务端配置
- 2.2.2 客户端配置
1 文件处理
1.1 打开和关闭文件
os.open()
函数能够打开一个文件,返回一个 *File
和一个 err
,对得到的文件使用 close()
方法能够关闭文件。
package mainimport ("fmt""os"
)// 打开关闭文件
func main() { // 打开当前目录下的 abc.txt 文件file,err := os.Open("./abc.txt")if err != nil { fmt.Println("文件打开失败",err)} else { fmt.Println("文件打开成功")file.Close() // 从内存释放资源fmt.Println("文件关闭成功")}
}
/*
文件打开成功
文件关闭成功
*/
1.2 读取文件
接收一个字节切片
,返回读取的字节数
和可能的具体错误
,读到文件末尾时会返回 0
和 io.EOF
。
func (f *File) Read(b []byte) (n int, err error)
1.2.1 简单示例
package mainimport ("fmt""io""os"
)// 打开关闭文件
func main() { // 打开当前目录下的 abc.txt 文件file,err := os.Open("./abc.txt")if err != nil { fmt.Println("文件打开失败",err)return}// 文件能打开defer file.Close() // 使用 defer 延迟开关,main 函数即将结束前释放文件资源fmt.Println("文件成功打开")// 读文件var tmp [128]byte // 定义一个字节切片,每次读 128 字节n,err := file.Read(tmp[:])// 文件读完if err == io.EOF { fmt.Println("文件已读完")return}// 读取中报错if err != nil { fmt.Println("Read from file failed,err",err)return}fmt.Printf("读取 %d 个字节\n",n)fmt.Println(string(tmp[:]))// fmt.Printf("获取的内容是:%s\n",string(tmp[:]))
}/*
读取 23 个字节
adadadsad
sdsadasdas
*/
循环读取文件
package mainimport ("fmt""io""os"
)// 打开关闭文件
func main() { // 打开当前目录下的 abc.txt 文件file,err := os.Open("./abc.txt")if err != nil { fmt.Println("文件打开失败",err)return}// 文件能打开defer file.Close() // 使用 defer 延迟开关,main 函数即将结束前释放文件资源fmt.Println("文件成功打开")// 读文件var tmp [128]byte // 定义一个字节切片,每次读 128 字节// for 循环读取内容,输出到程序中for { _,err := file.Read(tmp[:])// 文件读完if err == io.EOF { fmt.Println("文件已读完",err)return}// 读取中报错if err != nil { fmt.Println("Read from file failed,err",err)return}fmt.Printf("%s",string(tmp[:]))}
}
1.2.2 中文乱码
1.2.2.1 bufio
如果有乱码,可以使用 bufio
读取。bufio
在 file
的基础上封装了一层 API
,支持更多的功能。
package main
import ("fmt""os""io""bufio"
)// bufio 读数据
func main() { file,err := os.Open("./abc.txt")if err != nil { fmt.Println("文件打开失败",err)return}defer file.Close()// 封装一个 API 层// 利用缓冲区从文件读数据reader := bufio.NewReader(file)for { str,err := reader.ReadString('\n') // 字符if err == io.EOF { fmt.Print(str) // 要输出,否则不显示return}if err != nil { fmt.Println("读取文件内容失败",err)return}fmt.Print(str) // 取消文件中的自带换行}
}
示例:读取奇/偶数行
package mainimport ("bufio""fmt""io""os"
)// bufio 读数据
func main() { file, err := os.Open("./abc.txt")if err != nil { fmt.Println("文件打开失败", err)return}defer file.Close()// 利用缓冲区从文件读数据reader := bufio.NewReader(file)count := 0for { // 输出奇数行str, _, err := reader.ReadLine()count++if err == io.EOF { return}if err != nil { fmt.Println("读取文件内容失败", err)return}if count%2 == 1 { // 0 为偶数fmt.Println(string(str))}}
}
1.2.2.2 ioutil
package mainimport ("fmt""io/ioutil"
)
// ioutil 读取文件
func readFile(filename string) { content,err := ioutil.ReadFile(filename)if err != nil { fmt.Println("READ FILE FAILED,ERR:",err)return}fmt.Println(string(content))
}
func main() { readFile("./abc.txt")
}
1.3 写入文件
os.OpenFile()
函数能够以指定模式打开文件,从而实现文件写入相关功能。
func OpenFile(name string, flag int, perm FileMode)(*File,error) { ...
}
说明:
- name:要打开的文件名
- flag:打开文件的模式
模式种类:os.O_WRONLY
:只写os.O_CREATE
:创建文件os.O_RDONLY
:只读vos.O_RDWR
:读写os.O_TRUNC
:清空os.O_APPEND
:追加
- perm:文件权限,一个八进制数。r(读)04,w(写)02,x(执行)01。
1.3.1 Write 和 WriteString
package mainimport ("fmt""os"
)
// 打开文件支持文件写入
func main() { // 创建 tmp.txt 文件,分配权限 755file,err := os.OpenFile("tmp.txt",os.O_CREATE|os.O_WRONLY,0755)if err != nil { fmt.Println("打开文件失败",err)return}defer file.Close()// 定义写入内容str := "hello world"// 字节方式写入file.Write([]byte("this is test\n"))// 字符串方式写入defer file.WriteString(str)
}/* tmp.txt
this is test
hello world
*/
1.3.2 fmt.Fprintln
1.3.2.1 写入文件
fmt.Fprintln(f, v)
是 把 v 的内容写入到 f
中。
解释:
- f 是一个
io.Writer
类型的对象,表示你要写入数据的目标。常见的目标包括文件、标准输出(os.Stdout)、缓冲区等。 - v 是希望写入到 f 中的数据,v 可以是任何可以格式化的类型,例如 string、int、struct 等。
fmt.Fprintln(f, v)
的作用是将 v 的值写入 f 中,并且在写入的值后面会自动添加换行符 \n
。
package mainimport ("fmt""os"
)func main() {// 创建或打开文件f, err := os.Create("output.txt")if err != nil {fmt.Println("Error creating file:", err)return}defer f.Close()// 要写入文件的内容v := "Hello, world!"fmt.Fprintln(f, v) // 将 v 写入文件 f
}
1.3.2.2 写入标准输出
如果想把某个值写到控制台
fmt.Fprintln(os.Stdout, "Hello, Go!")
这个代码会将字符串 “Hello, Go!” 输出到标准输出(即控制台)
1.3.3 bufio.NewWriter
package mainimport ("fmt""os""bufio"
)
// 打开文件支持文件写入
func main() { file,err := os.OpenFile("tmp.txt",os.O_CREATE|os.O_WRONLY|os.O_TRUNC,0666)if err != nil { fmt.Println("打开文件失败",err)return}defer file.Close()// 定义写入内容write := bufio.NewWriter(file)defer write.Flush() // 确保缓冲区数据被写入for i:=0;i<10;i++ { write.WriteString("hello world\n") // 将数据写入缓存}
} /* tmp.txt
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
*/
1.3.4 ioutil.WriteFile
package mainimport ("fmt""io/ioutil"
)func main() { str := "hello world\nthis is test"// 字符串转换为字节数组写入err := ioutil.WriteFile("./tmp.txt",[]byte(str),0666)if err != nil { fmt.Println("文件写入错误",err)return}
}/* tmp.txt
hello world
this is test
*/
2 TCP&UDP
2.1 TCP
2.1.1 服务端
一个服务端连接多个客户端,例如:世界各地的用户使用自己电脑的浏览器访问淘宝网。
package mainimport ("fmt""net"
)
/* TCP 服务端 */
// 处理客户端连接函数
func process(conn net.Conn) { defer conn.Close()var buf [1024]byten,err := conn.Read(buf[:]) // 读取切片数据if err != nil { fmt.Println("read err:",err)return}str := string(buf[:n]) // 转换字符串fmt.Println("收到客户端发来的数据:",str)
}func main() { // 1. 监听端口listener,err := net.Listen("tcp","127.0.0.1:20000")// 连接失败处理if err != nil { fmt.Println("启动服务失败,err:",err)return}// 程序退出时释放端口defer listener.Close() for { // 2. 建立连接// conn 是返回的接口conn,err := listener.Accept()if err != nil { fmt.Println("接收客户端连接失败,err",err)continue // 继续阻塞,等待客户端再次连接}// 3. 启动一个 goroutine 处理客户端连接go process(conn)}
}
2.1.2 客户端配置
package mainimport ("fmt""net"
)/* TCP 客户端配置 */
func main() { // 1. 拨号方式建立与服务端连接conn,err := net.Dial("tcp","127.0.0.1:20000")if err != nil { fmt.Println("连接服务端失败,err:",err)return}// 注意:关闭连接位置,不能写在连接失败判断上面defer conn.Close()// 2. 向 server 发送信息// fmt.Fprintln(conn,"hello")_,err = conn.Write([]byte("hello,tom"))if err != nil { fmt.Println("发送消息失败,err:",err)return}
}
2.2 UDP
UDP是用户数据报协议,是一种无连接传输协议,不需要建立连接就可以直接发送和接收数据,属于不可靠的,没有时序的通信,UDP 实时性好,适合直播环境。
2.2.1 服务端配置
package mainimport ("fmt""net"
)/* UDP 服务端 */
func main() { // 1. 监听listener,err := net.ListenUDP("udp",&net.UDPAddr { IP: net.ParseIP("127.0.0.1"),Port: 30000,})if err != nil { fmt.Println("启动 server 失败,err:",err)return}// 退出时关闭资源defer listener.Close()// 循环收发数据for { var buf [1024]byte// 因为是无连接,所以需要知道对方地址 Addrn,addr,err := listener.ReadFromUDP(buf[:])if err != nil { fmt.Println("接收消息失败,err:",err)return}fmt.Printf("接收到来自 %v 的消息:%v\n",addr,string(buf[:n]))// 回复消息n,err = listener.WriteToUDP([]byte("hi"),addr)if err != nil { fmt.Println("回复失败,err:",err)return}}
}
2.2.2 客户端配置
package mainimport ("fmt""net"
)/* UDP 客户端 */
func main() { // 连接 UDP 服务器conn,err := net.Dial("udp","127.0.0.1:30000")if err != nil { fmt.Println("连接失败,err:",err)return}defer conn.Close()// 发送消息n,err := conn.Write([]byte("hello"))if err != nil { fmt.Println("发送失败,err:",err)return}// 接收消息var buf [1024]byten,err = conn.Read(buf[:]) // n 为返回的有效字节个数if err != nil { fmt.Println("接收消息失败,err:",err)return}fmt.Println("收到回复:",string(buf[:n]))
}