Golang的结构体和反射
目录
结构体
声明
结构体的使用
结构体和json数据的互相转换
反射
变量内置pair结构
reflect包
获取字段的类型和值
获取结构体字段、方法的名称、类型和值
解析结构体标签Tag
结构体
声明
// 声明一种新的类型 myint,是int的别名
type myint int// 定义一个结构体:把多种基本数据类型组合到一起变成一个新的类型
type Book struct {title stringauthor stringprice myint
}func changeBook(book Book) {//传递的是值类型,所以修改的是副本,不会影响原来的变量book.price = 999
}func changeBook1(book *Book) {// 指针类型可以修改结构体变量的值book.author = "新作者"
}func main() {var a myint = 10fmt.Println("a =", a)fmt.Printf("type of a is %T\n", a)var book1 Bookbook1.title = "Go 语言"book1.author = "老子"book1.price = 299fmt.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 stringAd intLevel 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 objecthero := 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"},}//编码的过程 结构体 ---> jsonjsonStr, 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 = astr, _ := 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的类型为nilfmt.Printf("r: %T\n", r)//r:pair<type:Book,value:book{}地址>r = b// 调用接口方法r.ReadBook()var w Writerw = 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.14reflectNum(num)
}
----------------------------------------------
PS D:\GoProject\firstGoProject> go run firstGoProject.go
type : float64
value: 3.14
获取结构体字段、方法的名称、类型和值
import ("fmt""reflect"
)type User struct {Id intName stringAge 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的valueinputValue := reflect.ValueOf(input)fmt.Println("inputValue is:", inputValue)//通过type获取里面的字段//1. 获取interface的reflect.Type,通过Type得到NumField,进行遍历//2. 得到每个field,数据类型//3. 通过filed有一个Interface()方法等到 对应的valuefor 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 resumefindTag(&re)
}
PS D:\GoProject\firstGoProject> go run firstGoProject.go
info: name doc: 我的名字
info: sex doc: 我的性别