Golang中的结构体和反射示例详解
作者:O.0)O.O(0.O
文章介绍了Go语言中结构体的使用、结构体与JSON数据的转换以及反射机制,反射允许在运行时获取类型信息、动态调用方法、访问属性和构造对象,文章还提到了使用reflect包来获取和操作结构体的字段、方法、类型和值,本文结合实例代码介绍的非常详细,感兴趣的朋友一起看看吧
结构体
声明
// 声明一种新的类型 myint,是int的别名 type myint int // 定义一个结构体:把多种基本数据类型组合到一起变成一个新的类型 type Book struct { title string author string price myint } func changeBook(book Book) { //传递的是值类型,所以修改的是副本,不会影响原来的变量 book.price = 999 } func changeBook1(book *Book) { // 指针类型可以修改结构体变量的值 book.author = "新作者" } func main() { var a myint = 10 fmt.Println("a =", a) fmt.Printf("type of a is %T\n", a) var book1 Book book1.title = "Go 语言" book1.author = "老子" book1.price = 299 fmt.Println("book1 =", book1) fmt.Printf("type of book1 is %T\n", book1) changeBook(book1) fmt.Println("--------------") fmt.Println("book1 =", book1) changeBook1(&book1) fmt.Println("--------------") fmt.Println("book1 =", book1) } ================================================= PS D:\GoProject\firstGoProject> go run firstGoProject.go a = 10 type of a is main.myint book1 = {Go 语言 老子 299} type of book1 is main.Book -------------- book1 = {Go 语言 老子 299} -------------- book1 = {Go 语言 新作者 299}
结构体的使用
import "fmt" //如果类名首字母大写,表示其他包也可以访问 type Hero struct { //如果类的属性首字母大写,表示其他包也可以访问,否则只能在本包中访问 Name string Ad int Level int } func (this Hero) GetName() string { return this.Name } func (this Hero) SetName(newName string) { //当前this是调用该方法的对象的拷贝 this.Name = newName } func (this Hero) ShowInfo() { fmt.Println("hero = ", this) } func (this *Hero) SetName1(newName string) { //这里的this是指针类型,所以可以修改对象的值 this.Name = newName } func main() { // create a Hero object hero := Hero{Name: "Alice", Ad: 100, Level: 10} var name = hero.GetName() fmt.Println("name = ", name) hero.ShowInfo() hero.SetName("Bob") hero.ShowInfo() hero.SetName1("Charlie") hero.ShowInfo() } ----------------------------------------------------- PS D:\GoProject\firstGoProject> go run firstGoProject.go name = Alice hero = {Alice 100 10} hero = {Alice 100 10} hero = {Charlie 100 10}
结构体和json数据的互相转换
import ( "encoding/json" "fmt" ) type Movie struct { Title string `json:"title"` //结构体的标签 Year int `json:"year"` Price int `json:"price"` Actors []string `json:"actors"` } func main() { movie := Movie{ Title: "The Dark Knight", Year: 2008, Price: 150, Actors: []string{"Christopher Nolan", "Robert Duvall"}, } //编码的过程 结构体 ---> json jsonStr, err := json.Marshal(movie) if err != nil { fmt.Println("json marshal error", err) } fmt.Printf("jsonStr = %s\n", jsonStr) //解码的过程 json ---> 结构体 //jsonStr = {"title":"The Dark Knight","year":2008,"price":150,"actors":["Christopher Nolan","Robert Duvall"]} myMovie := Movie{} err = json.Unmarshal(jsonStr, &myMovie) if err != nil { fmt.Println("json unmarshal error", err) return } fmt.Printf("myMovie = %v\n", myMovie) }
PS D:\GoProject\firstGoProject> go run firstGoProject.go jsonStr = {"title":"The Dark Knight","year":2008,"price":150,"actors":["Christopher Nolan","Robert Duvall"]} myMovie = {The Dark Knight 2008 150 [Christopher Nolan Robert Duvall]}
反射
反射(Reflection) 是指在程序运行时可以访问、检测和修改其自身状态或行为的一种能力。
具体来说,在面向对象编程中,反射允许程序:
- 在运行时获取类型信息(类名、方法、属性、注解等)
- 动态调用方法或访问属性
- 构造对象(即使编译时不知道具体类)
- 检查并操作类成员
反射机制允许程序在运行时获取类型信息并动态调用成员,而不需要在编译时确定具体的类或方法。
变量内置pair结构
一个变量中含有type 和 value ,称作pair
type分为 static type 和 concrete type,变量的type是两者中的一个(不能同时有两个type)
import "fmt" func main() { var a string //pair <type:static type(string), value:"Hello, World!"> a = "Hello, World!" //pair <type:constant type, value: nil> var allType interface{} //pair <type:string, value:"Hello, World!"> allType = a str, _ := allType.(string) fmt.Println(str) } ------------------------------------------------------- PS D:\GoProject\firstGoProject> go run firstGoProject.go Hello, World!
import ( "fmt" "io" "os" ) func main() { //tty: pair<type: *os.File, value: "/dev/tty" 文件描述符> tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0) if err != nil { fmt.Println(err) return } //r: pair<type: ,value: > var r io.Reader //r: pair<type: *os.File, value: "/dev/tty" 文件描述符> r = tty //w: pair<type: ,value: > var w io.Writer //w: pair<type: *os.File, value: "/dev/tty" 文件描述符> w = r.(io.Writer) w.Write([]byte("Hello, world!\n")) // 向终端输出 "Hello, world!\n" }
type Reader interface { ReadBook() } type Writer interface { WriteBook() } // 具体类型 type Book struct { } func (this *Book) ReadBook() { fmt.Println("Reading book...") } func (this *Book) WriteBook() { fmt.Println("Writing book...") } func main() { // 接口变量 b:pair<type:Book,value:book{}地址> b := &Book{} // 接口变量 r:pair<type:,value:> var r Reader //此时r的类型为nil fmt.Printf("r: %T\n", r) //r:pair<type:Book,value:book{}地址> r = b // 调用接口方法 r.ReadBook() var w Writer w = r.(Writer) w.WriteBook() } ------------------------------------------------------------- PS D:\GoProject\firstGoProject> go run firstGoProject.go r: <nil> Reading book... Writing book...
reflect包
获取字段的类型和值
import ( "fmt" "reflect" ) func reflectNum(arg interface{}) { fmt.Println("type :", reflect.TypeOf(arg)) fmt.Println("value:", reflect.ValueOf(arg)) } func main() { var num float64 = 3.14 reflectNum(num) } ---------------------------------------------- PS D:\GoProject\firstGoProject> go run firstGoProject.go type : float64 value: 3.14
获取结构体字段、方法的名称、类型和值
import ( "fmt" "reflect" ) type User struct { Id int Name string Age int } func (this User) Call() { fmt.Println("user is called ..") fmt.Printf("%v\n", this) } func main() { user := User{1, "John", 25} DoFileAndMethod(user) } func DoFileAndMethod(input interface{}) { //获取input的类型 inputType := reflect.TypeOf(input) fmt.Println("inputType is:", inputType.Name()) //获取input的value inputValue := reflect.ValueOf(input) fmt.Println("inputValue is:", inputValue) //通过type获取里面的字段 //1. 获取interface的reflect.Type,通过Type得到NumField,进行遍历 //2. 得到每个field,数据类型 //3. 通过filed有一个Interface()方法等到 对应的value for i := 0; i < inputType.NumField(); i++ { field := inputType.Field(i) value := inputValue.Field(i).Interface() fmt.Printf("field = %s,type = %v, value = %v\n", field.Name, field.Type, value) } fmt.Println("--------------------", inputType.NumMethod()) //通过type获取里面的方法,调用 for i := 0; i < inputType.NumMethod(); i++ { m := inputType.Method(i) fmt.Printf("%s,%v\n", m.Name, m.Type) } }
PS D:\GoProject\firstGoProject> go run firstGoProject.go inputType is: User inputValue is: {1 John 25} field = Id,type = int, value = 1 field = Name,type = string, value = John field = Age,type = int, value = 25 -------------------- 1 Call,func(main.User)
解析结构体标签Tag
import ( "fmt" "reflect" ) type resume struct { Name string `info:"name" doc:"我的名字"` Sex string `info:"sex" doc:"我的性别"` } func findTag(str interface{}) { t := reflect.TypeOf(str).Elem() for i := 0; i < t.NumField(); i++ { taginfo := t.Field(i).Tag.Get("info") tagdoc := t.Field(i).Tag.Get("doc") fmt.Println("info:", taginfo, "doc:", tagdoc) } } func main() { var re resume findTag(&re) }
PS D:\GoProject\firstGoProject> go run firstGoProject.go info: name doc: 我的名字 info: sex doc: 我的性别
到此这篇关于Golang的结构体和反射的文章就介绍到这了,更多相关go 结构体和反射内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!