Go异常处理、泛型和文件操作实例代码

2025-12-04 19:50

本文主要是介绍Go异常处理、泛型和文件操作实例代码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Go异常处理、泛型和文件操作实例代码》Go语言的异常处理机制与传统的面向对象语言(如Java、C#)所使用的try-catch结构有所不同,它采用了自己独特的设计理念和方法,:本文主要介绍Go异...

一:异常处理

go的异常处理可能是这门语言唯一的一个诟病了吧

由于 go 语言没有捕获异常的机制,导致每调一个函数都要接一下这个函数的 error

网上有个梗,叫做 error 是 go 的一等公民

常见的异常处理

向上抛

将错误交给上一级处理

一般是用于框架层,有些错误框架层面不能擅做决定,将错误向上抛不失为一个好的办法

package main

import (
  "errors"
  "fmt"
)

func Parent() error {
  err := method() // 遇到错误向上抛
  return err
}
func method() error {
  return errors.New("出错了")
}

func main() {
  fmt.Println(Parent())
}

中断程序

遇到错误直接停止程序

这种一般是用于初始化,一旦初始化出现错误,程序继续走下去也意义不大了,还不如中断掉

package main

import (
  "fmt"
  "os"
)

func init() {
  // 读取配置文件中,结果路径错了
  _, err := os.ReadFjavascriptile("xxx")
  if err != nil {
    panic(err.Error())
  }
}

func main() {
  fmt.Println("啦啦啦")
}

恢复程序

我们可以在一个函数里面,使用一个 defer,可以实现对 panic 的捕获

以至于出现错误不至于让程序直接崩溃

这种一般也是框架层的异常处理所做的

package main

import (
  "fmt"
  "runtime/debug"
)

func read() {
  defer func() {
    if err := recover(); err != nil {
      fmt.Println(err) // 捕获异常,打印错误信息
      // 打印错误的堆栈信息
      s := string(debug.Stack())
      fmt.Println(s)
    }
  }()
  var list = []int{2, 3}
  fmt.Println(list[2]) // 肯定会有一个panic
}

func main() {

  read()
}

当然,这个用于捕获异常的 defer 的延迟函数可以在调用链路上的任何一个函数上,但是 main中 捕获了会直接结束程序

  • panic 会层层向上抛,当前函数不处理,defer 放到 main 函数中也是会被处理的
  • 一旦 panic 发生,即使被 recover() 捕获,当前调用栈的“正常流程”也会中断

二:泛型

从 1.18 版本开始,Go 添加了对泛型的支持,即类型参数

泛型函数

如果我们要实现一个对int类型的求和函数

func add(a, b int) int {
  return a + b
}

但是这样写了之后,如果参数是 float 类型,int32 类型这些,就没办法使用了

难道要为每个类型都写一个这样的函数吗?

显然这就不合理

这个时候,泛型就上场了

func add[T int | float64 | int32](a, b T) T {
  return a + b
}

type Number interface {
	int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64
}

func plus[T Number](n1, n2 T) T {
	return n1 + n2
}

泛型结构体

package main

import (
  "encoding/json"
  "fmt"
)

type Response[T any] struct {
  Code int    `json:"code"`
  Msg  string `json:"msg"`
  Data T      `json:"data"`
}

func main() {
  type User struct {
    Name string `json:"name"`
  }

  type UserInfo struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
  }

  //user := Response{
  //  Code: 0,
  //  Msg:  "成功",
  //  Data: User{
  //    Name: "枫枫",
  //  },
  //}
  //byteData, _ := json.Marshal(usandroider)
  //fmt.Println(string(byteData))
  //userInfo := Response{
  //  Code: 0,
  //  Msg:  "成功",
  //  Data: UserInfo{
  //    Name: "枫枫",
  //    Age:  24,
  //  },
  //}
  //byteData, _ = json.Marshal(userInfo)
  //fmt.Println(string(byteData))

  var userResponse Response[User]
  json.Unmarshal([]byte(`{"code":0,"msg":"成功","data":{"name":"枫枫"}}`), &usandroiderResponse)
  fmt.Println(userResponse.Data.Name)
  var userInfoResponse Response[UserInfo]
  json.Unmarshal([]byte(`{"code":0,"msg":"成功","data":{"name":"枫枫","age":24}}`), &userInfoResponse)
  fmt.Println(userInfoResponse.Data.Name, userInfoResponse.Data.Age)
}

泛型切片

package main

type MySlice[T any] []T

func main() {
  var mySlice MySlice[string]
  mySlice = append(mySlice, "枫枫")
  var intSlice MySlice[int]
  intSlice = append(intSlice, 2)
}

泛型 map

package main

import "fmt"

type MyMap[K string | int, V any] map[K]V

func main() {
  var myMap = make(MyMap[string, string])
  myMap["name"] = "枫枫"
  fmt.Println(myMap)
}

三:文件操作

文件读取

一次性读取

byteData, _ := os.ReadFile("go_study/hello.txt")
fmt.Println(string(byteData))

获取当前go文件的路径

可以通过获取当前 go 文件的路径,然后用相对于当前 go 文件的路径去打开文件

// GetCurrentFilePath 获取当前文件路径
func GetCurrentFilePath() string {
  _, file, _, _ := runtime.Caller(1)
  return file
}

分片读

file, _ := os.Open("go_study/hello.txt")
defer file.Close()
for {
  buf := make([]byte, 1)
  _, err := file.Read(buf)
  if err == io.EOF {
    break
  }
  fmt.Printf("%s", buf)
}

带缓冲读

按行读

file, _ := os.Open("go_study/hello.txt")
buf := bufio.NewReader(file)
for {
  line, _, err := buf.ReadLine()
  fmt.Println(string(line))
  if err != nil {
    break
  }
}

指定分割符

file, _ := os.Open("go_study/hello.txt")
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanWords) // 按照单词读
//scanner.Split(bufio.ScanLines) // 按照行读
//scanner.Split(bufio.ScanRunes) // 按照中文字符读
//scanner.Split(bufio.ScanBytes) // 按照字节读读,中文会乱码

for scanner.Scan() {
  fmt.Println(scannerandroid.Text())
}

文件写入

一次性写

err := os.WriteFile("go_study/file1.txt", []byte("这是内容"), os.ModePerm)
fmt.Println(err)

文件的打开方式

常见的一些打开模式

// 如果文件不存在就创建
os.O_CREATE|os.O_WRONLY
// 追加写
os.O_APPEND|os.O_WRONLY
// 可读可写
os.O_RdwR

完整的模式

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_SYNC   int = syscall.O_SYNC   // 同步打开
  O_TRUNC  int = syscall.O_TRUNC  // 打开时清空文件
)

文件的权限

主要用于linux系统,在Windows下这个参数会被无视,代表文件的模式和权限位

文件复制

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

将 src 文件的内容复制到 dst 文件

read, _ := os.Open("go_study/file1.txt")
write, _ := os.Create("go_study/file3.txt") // 默认是 可读可写,不存在就创建,清空文件
n, err := io.Copy(write, read)
fmt.Println(n, err)

目录操作

dir, _ := os.ReadDir("go_study")
for _, entry := range dir {
  info, _ := entry.Info()
  fmt.Println(entry.Name(), info.Size()) // 文件名,文件大小,单位比特
}php

四:总结

到此这篇关于Go异常处理、泛型和文件操作的文章就介绍到这了,更多相关Go异常处理、泛型和文件操作内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!

这篇关于Go异常处理、泛型和文件操作实例代码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1156351

相关文章

Python+FFmpeg实现视频自动化处理的完整指南

《Python+FFmpeg实现视频自动化处理的完整指南》本文总结了一套在Python中使用subprocess.run调用FFmpeg进行视频自动化处理的解决方案,涵盖了跨平台硬件加速、中间素材处理... 目录一、 跨平台硬件加速:统一接口设计1. 核心映射逻辑2. python 实现代码二、 中间素材处

JAVA项目swing转javafx语法规则以及示例代码

《JAVA项目swing转javafx语法规则以及示例代码》:本文主要介绍JAVA项目swing转javafx语法规则以及示例代码的相关资料,文中详细讲解了主类继承、窗口创建、布局管理、控件替换、... 目录最常用的“一行换一行”速查表(直接全局替换)实际转换示例(JFramejs → JavaFX)迁移建

maven异常Invalid bound statement(not found)的问题解决

《maven异常Invalidboundstatement(notfound)的问题解决》本文详细介绍了Maven项目中常见的Invalidboundstatement异常及其解决方案,文中通过... 目录Maven异常:Invalid bound statement (not found) 详解问题描述可

C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解

《C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解》:本文主要介绍C++,C#,Rust,Go,Java,Python,JavaScript性能对比全面... 目录编程语言性能对比、核心优势与最佳使用场景性能对比表格C++C#RustGoJavapythonjav

MyBatis中的两种参数传递类型详解(示例代码)

《MyBatis中的两种参数传递类型详解(示例代码)》文章介绍了MyBatis中传递多个参数的两种方式,使用Map和使用@Param注解或封装POJO,Map方式适用于动态、不固定的参数,但可读性和安... 目录✅ android方式一:使用Map<String, Object>✅ 方式二:使用@Param

SpringBoot实现图形验证码的示例代码

《SpringBoot实现图形验证码的示例代码》验证码的实现方式有很多,可以由前端实现,也可以由后端进行实现,也有很多的插件和工具包可以使用,在这里,我们使用Hutool提供的小工具实现,本文介绍Sp... 目录项目创建前端代码实现约定前后端交互接口需求分析接口定义Hutool工具实现服务器端代码引入依赖获

Go语言实现桥接模式

《Go语言实现桥接模式》桥接模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立地变化,本文就来介绍一下了Go语言实现桥接模式,感兴趣的可以了解一下... 目录简介核心概念为什么使用桥接模式?应用场景案例分析步骤一:定义实现接口步骤二:创建具体实现类步骤三:定义抽象类步骤四:创建扩展抽象类步

GO语言实现串口简单通讯

《GO语言实现串口简单通讯》本文分享了使用Go语言进行串口通讯的实践过程,详细介绍了串口配置、数据发送与接收的代码实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目录背景串口通讯代码代码块分解解析完整代码运行结果背景最近再学习 go 语言,在某宝用5块钱买了个

利用Python在万圣节实现比心弹窗告白代码

《利用Python在万圣节实现比心弹窗告白代码》:本文主要介绍关于利用Python在万圣节实现比心弹窗告白代码的相关资料,每个弹窗会显示一条温馨提示,程序通过参数方程绘制爱心形状,并使用多线程技术... 目录前言效果预览要点1. 爱心曲线方程2. 显示温馨弹窗函数(详细拆解)2.1 函数定义和延迟机制2.2

SpringSecurity中的跨域问题处理方案

《SpringSecurity中的跨域问题处理方案》本文介绍了跨域资源共享(CORS)技术在JavaEE开发中的应用,详细讲解了CORS的工作原理,包括简单请求和非简单请求的处理方式,本文结合实例代码... 目录1.什么是CORS2.简单请求3.非简单请求4.Spring跨域解决方案4.1.@CrossOr