GO语言基础入门-Go读写文件操作 | 青训营笔记

106 阅读6分钟

前言

这是我参与「第五届青训营 」伴学笔记创作活动的第 9 天,其实第五届青训营已经正式开课n多天了,笔记不断更新中,都是我听完课之后的总结和平时自己的学习积累,分享出来给有需要的朋友。

本文内容

本文将涉及到Go语言断言、GO语言文件操作以及Go语言获取命令输入参数的详细使用和细节讲解。

Go语言基础

1.Go语言断言的使用
(1)什么是类型断言?

类型断言(Type Assertion)是一个使用在接口值上的操作,用于检查接口类型变量所持有的值是否实现了期望的接口或者具体的类型。断言可以帮助开发人员检查程序的正确性,并在发现错误时立即报告错误。

(2)断言的使用格式

断言基本格式

value, ok := x.(T)

该断言表达式会返回 x 的值(也就是 value)和一个布尔值(也就是 ok),可根据该布尔值判断 x 是否为 T 类型:

  • 如果 T 是具体某个类型,类型断言会检查 x 的动态类型是否等于具体类型 T。如果检查成功,类型断言返回的结果是 x 的动态值,其类型是 T。
  • 如果 T 是接口类型,类型断言会检查 x 的动态类型是否满足 T。如果检查成功,x 的动态值不会被提取,返回值是一个类型为 T 的接口值。
  • 无论 T 是什么类型,如果 x 是 nil 接口值,类型断言都会失败。
(3)断言使用案例

示例1:

package main
​
import (
    "fmt"
)
​
func main() {
    var x interface{}
    x = 10
    value, ok := x.(int)
    fmt.Print(value, ",", ok)
}

运行结果:

10,true

需要注意如果不接收第二个参数也就是上面代码中的 ok,断言失败时会直接造成一个 panic。如果 x 为 nil 同样也会 panic。

示例2:

package main
​
import (
    "fmt"
)
​
type Student struct {
}
​
// 编写一个函数,可以判断输入的参数是什么类型
func TypeJudge(items ...interface{}) {
    for index, x := range items {
        switch x.(type) {
        case bool:
            fmt.Printf("第%v个参数是bool类型,值是%v\n", index+1, x)
        case int, int32, int64:
            fmt.Printf("第%v个参数是int类型,值是%v\n", index+1, x)
        case float32:
            fmt.Printf("第%v个参数是float32类型,值是%v\n", index+1, x)
        case float64:
            fmt.Printf("第%v个参数是float64类型,值是%v\n", index+1, x)
        case string:
            fmt.Printf("第%v个参数是string类型,值是%v\n", index+1, x)
        case Student: //类型断言
            fmt.Printf("第%v个参数是Student类型,值是%v\n", index+1, x)
        case *Student: //类型断言
            fmt.Printf("第%v个参数是*Student类型,值是%v\n", index+1, x)
        default:
            fmt.Printf("第%v个参数类型不确定,值是%v\n", index+1, x)
        }
    }
}
​
func main() {
    var n1 float32 = 1.1
    var n2 float64 = 2.2
    var n3 int32 = 50
    var n4 string = "小王"
    address := "福建"
    n5 := true
    var stu Student = Student{}
    var stu2 *Student = &Student{}
    TypeJudge(n1, n2, n3, n4, address, n5, stu, stu2)
}
2.Go语言文件操作
(1)GO读文件操作

主要使用bufio包来实现文件的读取。

示例:

package main
​
import (
    "bufio"
    "fmt"
    "io"
    "os"
)
​
/* 读文件操作 */type Student struct {
}
​
func main() {
    fmt.Println()
    // 打开文件
    // 1.返回的是文件对象/指针/句柄,三种叫法
    file, err := os.Open("./test.txt")
    if err != nil {
        fmt.Println("文件打开错误")
    }
​
    //当函数退出时,要及时的关闭file
    defer file.Close() //要及时关闭file句柄,否则会有内存泄漏
    //创建一个*Reader ,是带缓冲的
    /*const(defaultBufSize = 4096) //默认的缓冲区为4096*/
​
    reader := bufio.NewReader(file)
    //循环的读取文件的内容
    for {
        str, err := reader.ReadString('\n') //读到一个换行就结束
        if err == io.EOF {                  //表示io.EOF表示文件的末尾
            break
        }
        //输出文件(输出的是file指针)
        fmt.Print(str)
    }
    fmt.Println("文件读取结束...")
​
}
(2)GO写文件操作

写文件和读文件一样,也是使用bufio包。

package main
​
import (
    "bufio"
    "fmt"
    "os"
)
​
func main() {
    //创建一个新文件,写入内容 5句"hello,Gardon "
    //1.打开文件
    filepath := "./test2.txt"
    //前面【os.O_WRONLY只写方式打开、os.O_RDWR 读写方式打开】
    //后面【os.O_CREATE创建、os.O_TRUNC清空、os.O_APPEND追加】
    file, err := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE, 0666)
    if err != nil {
        fmt.Println("open file err:", err)
        return
    }
    //及时关闭file句柄
    defer file.Close()
    //准备写入5句"hello,Gardon "
    str := "hello,Gardon\n"
    //写入时,使用带缓存的*Writer
    writer := bufio.NewWriter(file)
    for i := 0; i < 5; i++ {
        writer.WriteString(str)
    }
    writer.Flush()
}
​

因为writer是带缓存,因此在调用WriterString方法时,其实内容是先写入到缓存的,所以需要调用Flush方法,将带缓冲的数据真正写入到文件中。

(3)GO判断文件是否存在

golang判断文件或者文件夹是否存在的方法为使用os.Stat()函数返回的错误值进行判断

1.如果返回的错误为nil,说明文件或者文件夹存在

2.如果返回的错误类型使用os.IsNotExists()判断为true,说明文件或文件夹不存在

3.如果返回的错误为其他类型,则不确定是否存在

package main
​
import (
    "fmt"
    "os"
)
​
// 自己写一个返回函数
func PathExists(path string) (bool, error) {
    _, err := os.Stat(path)
    if err == nil {
        //文件或者目录存在
        return true, nil
    }
    if os.IsNotExist(err) {
        return false, nil
    }
    return false, err
​
}
​
func main() {
    flag, err := PathExists("./test2.txt")
    if flag {
        fmt.Println("文件存在")
    } else {
        fmt.Println("错误:", err)
    }
}
​
(4)GO语言文件拷贝操作
package main
​
import (
    "bufio"
    "fmt"
    "io"
    "os"
)
​
/*文件拷贝操作*/// 自己编写一个函数,接收两个文件路径srcFileName和dsFileName
func CopyFile(dsFileName string, srcFileName string) (writeen int64, err error) {
    srcFile, err := os.Open(srcFileName)
    if err != nil {
        fmt.Printf("open file err:%v\n", err)
    }
    defer srcFile.Close()
​
    //通过srcFile,获取到Reader
    reader := bufio.NewReader(srcFile)
​
    //打开dsFileName
    dsFile, err := os.OpenFile(dsFileName, os.O_WRONLY|os.O_CREATE, 0666)
    if err != nil {
        fmt.Println("open file err:", err)
        return
    }
    //通过dsFile,获取到Writer
    writer := bufio.NewWriter(dsFile)
    defer dsFile.Close()
    //因为writer是带缓存,因此在调用WriterString方法时,其实内容是先写入到缓存的
    //所以需要调用Flush方法,将带缓冲的数据真正写入到文件中。
    writer.Flush()
​
    return io.Copy(writer, reader)
}
​
func main() {
    //调用CopyFile 完成文件拷贝
    srcFilePath := "./picture1.jpg"
    dstFilePath := "./picture2.jpg"
    _, err := CopyFile(dstFilePath, srcFilePath)
    if err == nil {
        fmt.Println("拷贝完成!")
    } else {
        fmt.Println("拷贝错误,错误原因:", err)
    }
}
3.GO语言获取输入参数

获取用户输入的命令行参数的值,可以获取用户输入的命令行参数 可用来存储默认配置

package main
​
import (
    "flag"
    "fmt"
    "os"
)
​
func main() {
    fmt.Println("命令行的参数有", len(os.Args))
    //遍历os.Args切片,就可以得到输入所有的命令行参数
    for i, v := range os.Args {
        fmt.Printf("args[%v]=%v", i, v)
    }
​
    //2.可根据参数名获取参数值
    //先定义几个变量用于接收用户命令行中输入的-u后面的参数
    var user string
    var pwd string
    var host string
    var port int
    //"u",就是-u 指定参数
    //"",默认值
    //"用户名,默认为空" ,说明
    flag.StringVar(&user, "u", "", "用户名,默认为空")
    flag.StringVar(&pwd, "pwd", "", "密码,默认为空")
    flag.StringVar(&host, "h", "localhost", "主机名,默认为localhost")
    flag.IntVar(&port, "port", 3306, "主机名,默认为3306")
​
    //重要操作,解析调用prase方法
    flag.Parse()
    //输出结果
    fmt.Printf("user=%v pwd=%v host=%v port=%v", user, pwd, host, port)
​
}

总结

当我们对文件进行操作的时候,一定要记得操作完成后将文件句柄关闭,可以defer。

写在最后

本文是我的日常学习笔记,如果哪里有写错,麻烦请指出来,感谢。这里我也推荐大家多写笔记,写笔记是一个很好的习惯,可以帮助我们更好的吸收和理解学习的新知识,新的一年大家一起加油!