Golang中的结构体和反射示例详解

 更新时间:2025年10月11日 10:27:44   作者: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 结构体和反射内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 浅析Go语言中包的介绍与初始化

    浅析Go语言中包的介绍与初始化

    这篇文章主要为大家详细介绍了Go语言中包的介绍与初始化,从而搞清Go程序的执行次序,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解下
    2023-10-10
  • Golang 日志处理和正则处理的操作方法

    Golang 日志处理和正则处理的操作方法

    这篇文章主要介绍了Golang 日志处理和正则处理的操作方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2025-06-06
  • go内存队列list VS slice实现方式对比分析

    go内存队列list VS slice实现方式对比分析

    这篇文章主要为大家介绍了go内存队列list VS slice实现方式对比分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • Go语言net/http库使用详解

    Go语言net/http库使用详解

    net/http是Go语言标准库中用于处理HTTP协议的核心组件,它提供了完整HTTP客户端和服务器实现,这个包让开发者能够快速构建高性能的Web服务,无需依赖第三方框架,感兴趣的可以了解一下
    2025-10-10
  • 详解go语言中并发安全和锁问题

    详解go语言中并发安全和锁问题

    这篇文章主要介绍了go语言中并发安全和锁问题,包含互斥锁解锁过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-10-10
  • Golang的锁机制与使用技巧小结

    Golang的锁机制与使用技巧小结

    本文主要介绍了Golang的锁机制与使用技巧小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • golang简单获取上传文件大小的实现代码

    golang简单获取上传文件大小的实现代码

    这篇文章主要介绍了golang简单获取上传文件大小的方法,涉及Go语言文件传输及文件属性操作的相关技巧,需要的朋友可以参考下
    2016-07-07
  • 一文详解如何在Golang中实现JWT认证与授权

    一文详解如何在Golang中实现JWT认证与授权

    在现代Web应用中,安全性是一个非常重要的课题,JWT作为一种常用的认证与授权机制,已被广泛应用于各种系统中,下面我们就来看看如何在Golang中实现JWT认证与授权吧
    2025-03-03
  • Go语言实现统计字符串中每个字符出现的次数

    Go语言实现统计字符串中每个字符出现的次数

    这篇文章主要为大家详细介绍了如何使用Go语言开发一个简易频率分析器,实现统计字符串中每个字符出现的次数,感兴趣的小伙伴可以了解一下
    2025-07-07
  • Go中的fuzz模糊测试使用实战详解

    Go中的fuzz模糊测试使用实战详解

    这篇文章主要为大家介绍了Go中的fuzz模糊测试使用实战详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12

最新评论