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


    一、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):调用值对应的方法,传递参数并返回结果。
    	
    	通过使用这些方法,你可以在运行时检查和操作任意类型的对象。例如,你可以获取一个结构体类型的字段名和值,动态调用函数,或者创建新的对象。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    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}  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    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  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    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  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    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  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    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  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    二、 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    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.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    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  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    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.  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
  • 相关阅读:
    基于SSM的“基于Apriori算法的网络书城”的设计与实现(源码+数据库+文档)
    Android平台实现系统内录(捕获播放的音频)并推送RTMP服务技术方案探究
    【文件包含漏洞-03】文件包含漏洞的六种利用方式
    【基础计算】ESDF栅格距离图计算并行加速版 (附源码)
    347. 前 K 个高频元素——大顶堆、小顶堆
    N-144基于微信小程序在线订餐系统
    【Spring】IDEA&spring-mybatis的整合----关于配置文件的整合、AOP事务处理(配置&注解)
    Java 多种获取项目路径下的文件
    openGauss数据库客户端连接工具之Datastudio安装
    权威认可 | Smartbi为何屡获市场认可,多个权威报告给出答案
  • 原文地址:https://blog.csdn.net/MeiJin_/article/details/132628507