`

golang笔记——struct

 
阅读更多

1、定义一个结构体

type User struct {
    userid   int
    username string
    password string
}

 

2、初始化一个结构体

  有两种情况,一是得到结构体的对象,一是得到结构的对象指针,分别有三种方式:

复制代码
 //第1种方式,先声明对象,再初始化
    var player1 Player
    player1.userid = 1
    player1.username = "lina1"
    player1.password = "123456"
  
    //第2种方式,声明同时初始化
    player2 := Player{2, "lina2", "123456"}

    //第3种方式,通过 field:value 形式初始化,该方式可以灵活初始化字段的顺序
    player3 := Player{username: "lina3", password: "123456", userid: 3}

    //上面三种初始化方式都是生产对象的,相应如果想初始化得到对象指针的三种方法如下:
    //第1种方式,使用 new 关键字
    player4 := new(Player)
    player4.userid = 4
    player4.username = "lina4"
    player4.password = "123456"

    //第2种方式,声明同时初始化
    player5 := &Player{5, "lina2", "123456"}

    //第3种方式,通过 field:value 形式初始化,该方式可以灵活初始化字段的顺序
    player6 := &Player{username: "lina3", password: "123456", userid: 6}
复制代码

 

3、对象与对象指针的区别(更确切的说应该是值类型和指针类型)

  与C/C++类似,GO语言也存在对象与对象的指针,但不同的是,GO语言中没有 -> 操作符来调用指针所属的成员,而与一般对象一样,都是使用 . 来调用。

  对于一个函数(或方法),如果函数的参数(或接收者)是对象指针时,表示此对象是可被修改的;相反的,如果是对象时,表示是不可修改的(但如果该对象本身就是引用类型,如 map\func\chan 等,则本质上是可以修改的)。所以一般的做法是,方法的接收者习惯性使用对象指针,而不是对象,一方面可以在想修改对象时进行修改,另一方面也减少参数传递的拷贝成本。

  另外,有一点尤为特殊,如果是作为函数的参数,则函数定义时,是使用对象还是对象指针,是有本质区别的,在使用对象作为参数的函数中,不能传入对象指针,同样的,在使用对象指针作为参数的函数中,也不能传入对象,否则编译器会报错。但如果是方法,则接收者定义为对象还是对象指针,都可以接收对象和对象指针的调用。下面我们来定义相关的函数和方法如下:

复制代码
//传入 Player 对象参数
func print_obj(player Player) {
    //player.username = "new"  //修改并不会影响传入的对象本身
    log.Println("userid:", player.userid)
}

//传入 Player 对象指针参数
func print_ptr(player *Player) {
    player.username = "new"
    log.Println("userid:", player.userid)
}

//接收者为 Player 对象的方法,方法接收者的变量,按照 GO 语言的习惯一般不用 this/self ,而是使用接收者类型的第一个小写字母,可以看标准库中的代码风格。
func (p Player) m_print_obj() {
    //p.username = "new"  //修改并不会影响传入的对象本身
   log.Println("self userid:", p.userid) 
} 

//接收者为 Player 对象指针的方法
func (p *Player) m_print_ptr() { 
  p.username = "new" 
  log.Println("self userid:", p.userid) 
}
复制代码

   然后测试一下函数跟方法的调用:

复制代码
    print_obj(player2)
    //print_ptr(player2)        //无法调用,编译出错
    player2.m_print_obj()
    player2.m_print_ptr()

    //print_obj(player6)        //无法调用,编译出错
    print_ptr(player6) 
    player6.m_print_obj()
    player6.m_print_ptr()
复制代码

   既然对于对象与对象指针的区别,方法的处理很特殊,那么将一个对象传入到接收者为对象指针的方法中,及将一个对象指针传入到一个接收者为对象的方法中,能不能修改传入对象的值呢?答案是,由方法的定义决定,而不是方法的调用者类型决定。

 

4、匿名字段

  结构体里的字段可以只有类型名,而没有字段名,这种字段称为匿名字段。匿名字段可以是一个结构体、切片等复合类型,也可以是 int 这样的简单类型。但建议不要把简单类型作为匿名字段。

复制代码
type Pet struct {
    id      int
    petname string
}

type Player struct {
    id int
    Pet
    int
}

func main() {
    var player1 Player
    player1.petname = "pet1" //可以直接访问匿名字段中的成员,就像访问自己的成员一样
    player1.int = 3          //一般不推荐将简单类型作为匿名字段,如果有多个匿名的int,这里就没法处理了
    player1.id = 1           //如果外层跟内层字段名重复的话,优先取外层字段
    player1.Pet.id = 10      //如果外层跟内层字段名重复的话,可以通过这种形式来访问内层字段
}
复制代码

 


一个命名为S的结构体类型将不能再包含S类型的成员:因为一个聚合的值不能包含它自身。(该限制同样适应于数组。)但是S类型的结构体可以包含*S指针类型的成员,这可以让我们创建递归的数据结构,比如链表和树结构等。

 

如果结构体没有任何成员的话就是空结构体,写作struct{}。它的大小为0,也不包含任何信息,但是有时候依然是有价值的。有些Go语言程序员用map带模拟set数据结构时,用它来代替map中布尔类型的value,只是强调key的重要性,但是因为节约的空间有限,而且语法比较复杂,所有我们通常避免避免这样的用法。

seen := make(map[string]struct{}) // set of strings
// ...
if _, ok := seen[s]; !ok {
    seen[s] = struct{}{}
    // ...first time seeing s...
}

结构体可以作为函数的参数和返回值,如果结构体较大,一般使用指针参数,而且如果要在函数修改结构体,则必须使用指针形式。go语言中所有的函数参数都是值拷贝。

如果结构体的全部成员都是可比较的,则该结构体也可比较,则可作为Map的key类型。

得意于匿名嵌入的特性,我们可以直接访问叶子属性而不需要给出完整的路径:


var w Wheel
w.X = 8            // equivalent to w.Circle.Point.X = 8
w.Y = 8            // equivalent to w.Circle.Point.Y = 8
w.Radius = 5       // equivalent to w.Circle.Radius = 5
w.Spokes = 20
 

不幸的是,结构体字面值并没有简短表示匿名成员的语法, 因此下面的语句都不能编译通过:


w = Wheel{8, 8, 5, 20}                       // compile error: unknown fields
w = Wheel{X: 8, Y: 8, Radius: 5, Spokes: 20} // compile error: unknown fields


到目前为止,我们看到匿名成员特性只是对访问嵌套成员的点运算符提供了简短的语法糖。稍后,我们将会看到匿名成员并不要求是结构体类型;其实任何命令的类型都可以作为结构体的匿名成员。但是为什么要嵌入一个没有任何子成员类型的匿名成员类型呢?

答案是匿名类型的方法集。简短的点运算符语法可以用于选择匿名成员嵌套的成员,也可以用于访问它们的方法。实际上,外层的结构体不仅仅是获得了匿名成员类型的所有成员,而且也获得了该类型导出的全部的方法。这个机制可以用于将一个有简单行为的对象组合成有复杂行为的对象。组合是Go语言中面向对象编程的核心

 

结体体定义时,可以为每一个字段添加一个 Tag,比如使用内置Json库时,就可能用到这个Tag。具体看元数据和反射。

分享到:
评论

相关推荐

    golang struct 自动生成工具

    https://github.com/whr-helen/go-struct-auto 自动构建工具使用 安装包命令:go get github.com/whr-helen/go-struct-auto 注释:参数信息 -host host改为自己数据库的地址(默认127.0.0.1) -port port改为...

    Golang 笔记 第四版 高清版.zip

    笔记会讲解Go的接口(Interface)和结构体(Struct),如何通过它们实现面向对象的设计。Go并不像Java或C++那样有类的概念,而是通过接口和值传递来实现多态,这使得代码更加简洁且易于理解。 此外,Go语言的并发...

    Go-SQL2Struct一款根据sql语句自动生成golang结构体的chrome插件

    SQL2Struct是一款对golang开发者友好的chrome插件,根据在mysql中创建数据表的sql语句,自动生成golang中的struct,在golang开发者使用诸如gorm之类的框架时,可以很好的把mysql中的数据表与orm的结构体关联起来。

    mysql表里面的字段转换成golang的struct

    把mysql表里面的字段转换成golang的struct,可以再orm里面使用

    Go 学习笔记——雨痕

    Go语言,又称Golang,是一种静态类型的编程语言,由Google开发,于2007年首次对外公布,并在2009年进行了开源。Go语言的设计哲学是简洁、快速和安全。它支持垃圾回收,具有类型系统和一些并发控制机制。 变量的定义...

    zinx —— golang —— MMO游戏服务器开发对应客户端

    《Zinx:Golang构建MMO游戏服务器及客户端解析》 在现代网络游戏开发中,后端服务器扮演着至关重要的角色,它们负责处理玩家交互、游戏逻辑、数据存储等一系列任务。Zinx是一个用Golang编写的轻量级网络框架,特别...

    golang如何使用struct的tag属性的详细介绍

    在Go语言中,`struct` 是一种非常重要的数据结构,用于定义自定义类型,并且可以包含多个字段。在`struct` 的字段定义中,我们可以使用`tag` 属性来为每个字段提供额外的信息,这对于与外部数据格式(如 JSON、XML ...

    golang中struct和interface的基础使用教程

    本文主要给大家介绍了关于golang中struct和interface的相关内容,是属于golang的基本知识,下面话不多说了,来一起看看详细的介绍吧。 struct struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套...

    golang中struct和[]byte的相互转换示例

    在Golang编程语言中,有时我们需要将结构体(`struct`)与字节切片(`[]byte`)之间进行转换,这在处理网络数据传输、序列化或反序列化等场景中非常常见。本文将详细介绍如何在Golang中实现`struct`到`[]byte`以及`...

    moutsea#TechFlow#Golang——Go语言中的变量声明1

    第二点是Golang当中自带了map类型,像是java以及C++虽然也有map,但是都不是原生支持的,而是必须要通过引入包才可以使用的 第一种方式最复杂,我们不

    awesome-go-datastruct:golang的DataStruct

    数据结构(go语言实现)本项目是由一个在校本科生做的,所以文档方面,英文不会有了,但是中文文档会尽力写的详细一些,希望大佬们觉得不错的话可以多多支持。这个项目中会有那些数据结构呢?单向链表(LinkedList)...

    Golang学习笔记(六):struct

    这篇Golang学习笔记主要探讨了struct的声明与初始化、匿名字段(继承)、方法以及方法的继承与重写。 1. 声明及初始化: 在Golang中,我们可以使用`type`关键字来声明一个新的struct类型。例如,定义一个`person`...

    xm2struct:将 xml 转换为 golang 结构的转换器

    `xm2struct`工具正是为此目的设计的,它是一个将XML转换为Golang结构体的转换器。 `xm2struct`的工作原理是解析XML文档,分析其元素和属性,然后生成相应的Golang结构体定义。这对于处理XML数据的Go程序员来说非常...

    大家一起学Golang——结构体、方法

    大家一起学Golang——结构体、方法 结构体类型 空结构体 结构体标签 匿名字段 方法 重写 结构体类型 结构体类型通过一系列的且唯一的字段来声明。在go中数组切片只能存储同一类型的数据,但结构体用户可以自定义将...

    雨痕golang学习笔记第四版 加上书签版

    《雨痕golang学习笔记第四版 加上书签版》是针对Go语言学习者的参考资料,作者雨痕在书中详细记录了从2012年开始学习Go语言至今的经验与成果。本书内容全面,涵盖了Go语言的基础知识、数据结构、函数特性、并发编程...

    大家一起学Golang——文件操作

    大家一起学Golang——文件操作 文件操作 对文件操作几乎每个编程语言都有,Go后端开发中对日志操作较多。 创建 、打开文件 创建两种方式: func Create(name string) (file *FIle, err Error) 返回文件对象,默认...

    初级golang个人笔记

    初级 Golang 个人笔记 本笔记主要讲解了 Golang 的基本知识点,包括 Golang 的常用命令、基本语法、执行流程分析等。 一、Golang 的常用命令 Golang 提供了许多有用的命令,例如: * build: 编译包和依赖 * ...

    Golang 入门笔记.md

    Golang 入门笔记.md

    GoLang 学习笔记。

    Go语言,通常称为Golang,是一种由Google开发的静态类型、编译型语言。它自2007年被设计,2009年首次向公众发布,并在2012年3月29日正式发布了Go1,也就是Go语言的第一个稳定版本。以下是从提供的【部分内容】中提炼...

    复印机:golang复印机,将值从struct复制到struct等

    影印机 我是复印机,我将所有内容都复制到另一个 产品特点 ...// Tags in the destination Struct provide instructions to copier.Copy to ignore // or enforce copying and to panic or return an error

Global site tag (gtag.js) - Google Analytics