Go语言高阶:Reflection反射与Files操作 详细示例教程

目录标题

  • 一、Reflection反射
    • 1. What is reflection? 什么是反射
    • 2. Inspect a variable and find its type 检查变量并找到它的类型
    • 3. Reflect.Type and reflect.Value 反射类型和值
    • 4. Reflect.Kind 查看底层种类
    • 5. NumField() and Field() methods 字段数量和索引值方法
    • 6. Int() and String() methods 整型和字符型方法
    • 7. Complete Program 完整示例
  • 二、 Reading Files
    • 1. Reading Files 读取文件
    • 2. Using absolute file path 使用绝对路径
    • 3. Passing the file path as a command line flag 将文件路径作为命令行标志传递
    • 4. Reading a file in small chunks
    • 5. Reading a file line by line 逐行读取文件

一、Reflection反射

1. What is reflection? 什么是反射

	反射是Go中的高级主题之一,在Go语言中反射(reflection)是指在程序运行时动态地检查类型信息和操作对象的能力。通过反射,你可以在运行时获取类型的信息,访问和修改对象的字段和方法,以及动态地调用函数。 Go语言中的反射由reflect包提供支持。该包中的Type和Value类型提供了访问和操作类型和对象的方法。
	要使用反射,首先需要使用reflect.TypeOf()函数获取一个值的类型信息,或者使用reflect.ValueOf()函数获取一个值的反射对象。这些函数返回的类型对象或值对象包含了有关值的类型、字段、方法等信息。
	
	反射对象的常用方法包括:
		Type.Kind():返回类型的种类,如整数、字符串、结构体等。
		Type.Name():返回类型的名称。
	    Type.Field(i int):返回结构体类型的第i个字段的反射对象。
	    Type.NumField():返回结构体类型的字段数量。
	    Value.Interface():将反射对象转换为普通的接口类型。
	    Value.Kind():返回值的种类,如整数、字符串、结构体等。
	    Value.String():返回值的字符串表示。
	    Value.Field(i int):返回结构体类型值的第i个字段的反射对象。
	    Value.NumField():返回结构体类型值的字段数量。
	    Value.Method(i int):返回值的第i个方法的反射对象。
	    Value.Call(args []Value):调用值对应的方法,传递参数并返回结果。
	
	通过使用这些方法,你可以在运行时检查和操作任意类型的对象。例如,你可以获取一个结构体类型的字段名和值,动态调用函数,或者创建新的对象。

2. Inspect a variable and find its type 检查变量并找到它的类型

        package main

        import (
            "fmt"
        )

        type order struct {
            ordId      int
            customerId int
        }

        type employee struct {
            name    string
            id      int
            address string
            salary  int
            country string
        }

        func createQuery(b order) string {
            i := fmt.Sprintf("insert into order values(%d, %d)", b.ordId, b.customerId)
            return i
        }

        func createQuerySet(b employee) string {
            i := fmt.Sprintf("insert into order values(%s, %d, %s, %d, %s)", b.name, b.id, b.address, b.salary, b.country)
            return i
        }


        func main() {
            a := 10
            fmt.Printf("%d, %T\n", a, a)
            b := order{
                171103,
                1006,
            }

            e := employee{
                "Like",
                1,
                "Shanghai",
                999999,
                "Minghang",
            }

            fmt.Println(createQuery(b))
            fmt.Println(createQuerySet(e))
        }


        // 10, int
        // insert into order values(171103, 1006)
        // insert into order values(Like, 1, Shanghai, 999999, Minghang)

3. Reflect.Type and reflect.Value 反射类型和值

        package main

        import (  
            "fmt"
            "reflect"
        )

        type order struct {  
            ordId      int
            customerId int
        }

        func createQuery(q interface{}) {  
            t := reflect.TypeOf(q)
            v := reflect.ValueOf(q)
            fmt.Println("Type ", t)
            fmt.Println("Value ", v)


        }
        func main() {  
            o := order{
                ordId:      456,
                customerId: 56,
            }
            createQuery(o)

        }

        // Type  main.order  
        // Value  {456 56}  

4. Reflect.Kind 查看底层种类

        package main

        import (  
            "fmt"
            "reflect"
        )

        type order struct {  
            ordId      int
            customerId int
        }

        func createQuery(q interface{}) {  
            t := reflect.TypeOf(q)
            k := t.Kind()
            fmt.Println("Type ", t)
            fmt.Println("Kind ", k)


        }
        func main() {  
            o := order{
                ordId:      456,
                customerId: 56,
            }
            createQuery(o)

        }

        // Type  main.order  
        // Kind  struct  

5. NumField() and Field() methods 字段数量和索引值方法

        package main

        import (  
            "fmt"
            "reflect"
        )

        type order struct {  
            ordId      int
            customerId int
        }

        func createQuery(q interface{}) {   
            if reflect.ValueOf(q).Kind() == reflect.Struct {	// struct == struct
                v := reflect.ValueOf(q) 	// {456 56}
                fmt.Println("Number of fields", v.NumField())		// 2
                for i := 0; i < v.NumField(); i++ {
                    fmt.Printf("Field:%d type:%T value:%v\n", i, v.Field(i), v.Field(i))
                }
            }

        }
        func main() {  
            o := order{
                ordId:      456,
                customerId: 56,
            }
            createQuery(o)
        }


        // Number of fields 2  
        // Field:0 type:reflect.Value value:456  
        // Field:1 type:reflect.Value value:56  

6. Int() and String() methods 整型和字符型方法

        package main

        import (  
            "fmt"
            "reflect"
        )

        func main() {  
            a := 56
            x := reflect.ValueOf(a).Int()
            fmt.Printf("type:%T value:%v\n", x, x)
            b := "Naveen"
            y := reflect.ValueOf(b).String()
            fmt.Printf("type:%T value:%v\n", y, y)

        }


        // type:int64 value:56  
        // type:string value:Naveen  

7. Complete Program 完整示例

        package main

        import (  
            "fmt"
            "reflect"
        )

        type order struct {  
            ordId      int
            customerId int
        }

        type employee struct {  
            name    string
            id      int
            address string
            salary  int
            country string
        }

        func createQuery(q interface{}) {  
            if reflect.ValueOf(q).Kind() == reflect.Struct {
                t := reflect.TypeOf(q).Name()
                query := fmt.Sprintf("insert into %s values(", t)		// 输出传入的values
                v := reflect.ValueOf(q)		// 赋值v
                for i := 0; i < v.NumField(); i++ {
                    switch v.Field(i).Kind() {
                    case reflect.Int:
                        if i == 0 {
                            query = fmt.Sprintf("%s%d", query, v.Field(i).Int())
                        } else {
                            query = fmt.Sprintf("%s, %d", query, v.Field(i).Int())
                        }
                    case reflect.String:
                        if i == 0 {
                            query = fmt.Sprintf("%s\"%s\"", query, v.Field(i).String())
                        } else {
                            query = fmt.Sprintf("%s, \"%s\"", query, v.Field(i).String())
                        }
                    default:
                        fmt.Println("Unsupported type")
                        return
                    }
                }
                query = fmt.Sprintf("%s)", query)
                fmt.Println(query)
                return

            }
            fmt.Println("unsupported type")
        }

        func main() {  
            o := order{
                ordId:      456,
                customerId: 56,
            }
            createQuery(o)

            e := employee{
                name:    "Naveen",
                id:      565,
                address: "Coimbatore",
                salary:  90000,
                country: "India",
            }
            createQuery(e)
            i := 90
            createQuery(i)

        }

        //  insert into order values(456, 56)  
        //  insert into employee values("Naveen", 565, "Coimbatore", 90000, "India")  
        //  unsupported type  

二、 Reading Files

1. Reading Files 读取文件

        package main

        import (
            "fmt"
            "os"
        )

        func main() {
            contents, err := os.ReadFile("test.txt")
            if err != nil {
                fmt.Println("File reading error", err)
                return
            }
            fmt.Println("Contents os file:", string(contents))
        }

        // Contents os file: Hello World. Welcome to file handling in GO

2. Using absolute file path 使用绝对路径

        package main

        import (
            "fmt"
            "os"
        )

        func main() {
            contents, err := os.ReadFile("D:/Go/oop/test.txt")
            if err != nil {
                fmt.Println("File reading error", err)
                return
            }
            fmt.Println("Contents os file:", string(contents))
        }

        // Contents os file: Hello World. Welcome to file handling in GO

3. Passing the file path as a command line flag 将文件路径作为命令行标志传递

        package main  
        import (  
            "flag"
            "fmt"
        )

        func main() {  
            fptr := flag.String("fpath", "test.txt", "file path to read from")
            flag.Parse()
            contents, err := os.ReadFile(*fptr)
            if err != nil {
                fmt.Println("File reading error", err)
                return
            }
            fmt.Println("Contents of file: ", string(contents))
        }

        // Contents of file:  Hello World. Welcome to file handling in GO.

4. Reading a file in small chunks

        package main

        import (
            "bufio"
            "flag"
            "fmt"
            "io"
            "log"
            "os"
        )

        func main() {
            targetPath := flag.String("targetPath", "test.txt", "file path to read from")
            flag.Parse() // 进行命令行参数的解析 将相应的值赋给标志变量targetPath

            f, err := os.Open(*targetPath) // err: nil  f: *os.File
            if err != nil {
                log.Fatal(err) // 将错误信息打印到标准错误输出
            }
            defer func() { // 延迟开启匿名函数一直循环 如果关闭文件时发送错误 log处理错误
                if err = f.Close(); err != nil {
                    log.Fatal(err)
                }
            }()

            r := bufio.NewReader(f) // 创建了一个 bufio.Reader 对象r用于逐行读取文件内容
            b := make([]byte, 3)
            for {
                n, err := r.Read(b) //  r.Read(b) 方法读取文件内容 将读取到的内容存储在字节切片b中 并返回读取的字节数n和可能出现的错误err
                if err == io.EOF {  // 如果读取到文件末尾输出
                    fmt.Println("Finished reading file")
                    break
                }
                if err != nil { // 如果读取文件发生错误
                    fmt.Println("Error %s reading files", err)
                    break
                }
                fmt.Println(string(b[0:n])) // 输出切片内容 切片容量3
            }
        }


        // Hel  
        // lo  
        // Wor  
        // ld.  
        //  We
        // lco  
        // me  
        // to  
        // fil  
        // e h  
        // and  
        // lin  
        // g i  
        // n G  
        // o.  
        // finished reading file  

5. Reading a file line by line 逐行读取文件

        package main

        import (  
            "bufio"
            "flag"
            "fmt"
            "log"
            "os"
        )

        func main() {  
            fptr := flag.String("fpath", "test.txt", "file path to read from")
            flag.Parse()

            f, err := os.Open(*fptr)
            if err != nil {
                log.Fatal(err)
            }
            defer func() {
                if err = f.Close(); err != nil {
                log.Fatal(err)
            }
            }()
            s := bufio.NewScanner(f)
            for s.Scan() {
                fmt.Println(s.Text())
            }
            err = s.Err()
            if err != nil {
                log.Fatal(err)
            }
        }

        // Hello World. Welcome to file handling in Go.  
        // This is the second line of the file.  
        // We have reached the end of the file.  

你可能感兴趣的:(Go,golang,开发语言,后端,go)