golang之结构体和方法
结构体的定义
结构体是将零个或者多个任意类型的命令变量组合在一起的聚合数据类型。
每个变量都叫做结构体的成员。
其实简单理解,Go语言的结构体struct和其他语言的类class有相等的地位,但是GO语言放弃了包括继承在内的大量面向对象的特性,只保留了组合这个基础的特性。
所有的Go语言类型除了指针类型外,都可以有自己的方法。
先通过一个下的例子理解struct。
package main import "fmt" type Student struct {
Name string
Age int
Sex string
Score int
} func main() {
var stu Student
stu.Name = "zhangsan"
stu.Age =
stu.Sex = "male"
stu.Score =
fmt.Printf("name:%s\n age:%d\n sex:%s\n score:%d\n", stu.Name, stu.Age, stu.Sex, stu.Score) fmt.Printf("%v\n", stu)
fmt.Printf("%+v\n", stu)
fmt.Printf("%#v\n", stu)
}
关于Go中的struct:
- 用于定义复杂的数据结构
- struct里面可以包含多个字段(属性),字段可以是任意类型
- struct类型可以定义方法(注意和函数的区别)
- struct类型是值类型
- struct类型可以嵌套
- Go语言没有class类型,只有struct类型
定义一个struct
struct声明:
type 标识符 struct {
field1 type
field2 type
}
例子:
type Student struct {
Name string
age int
}
struct中字段的访问,和其他语言一样使用“.”点这个符号
var stu Student
stu.Name = "tom"
stu.Age = 18
赋值的时候我们是通过stu.Name同样的我们访问的时候也是通过stu.Name
struct定义的三种形式
type Student struct {
Name string
age int
}
对于上面这个结构体,我们定义的三种方式有:
- var stu student
- var stu *Student = new(Student)
- var stu *Student = &Student
上面三种方法中,方法2和方法3的效果是一样的,返回的都是指向结构体的指针,访问的方式如下:
stu.Name,stu.Age
(*stu).Name,(*stu).Age而这种方法中可以换成上面的方法直接通过stu.Name访问
这里是go替我们做了转换了,当我们通过stu.Name访问访问的时候,go会先判断stu是值类型还是指针类型如果是指针类型,会替我们改成(*stu).Name
struct中所有字段的内存是连续的
Go 中的struct没有构造函数,一般通过工厂模式来解决,通过下面例子理解:
package main import "fmt" type Student struct {
Name string
Age int
} func newStudent(name string, age int) *Student {
return &Student{
Name: name, //后面需加上逗号,不然会报错
Age: age, //后面需要加上逗号,不然会报错
}
} func main() {
stu := newStudent("tom", )
fmt.Println(stu)
fmt.Println(stu.Name)
}
struct中的tag
我们可以为struct中的每个字段,写上一个tag。这个tag可以通过反射的机制获取到,最常用的场景就是json序列化和反序列化
下面先写一个正常我们序列化的例子:
package main import (
"encoding/json"
"fmt"
) type Student struct {
Name string
Age int
} func main() {
var stu Student
stu.Name = "tom"
stu.Age = data, err := json.Marshal(stu)
if err != nil {
fmt.Printf("json marshal fail,fail message is %v\n", err)
return
}
fmt.Printf("json marshal result is %s\n", data)
}
运行结果如下:
json marshal result is {"Name":"tom","Age":22}
注意:这里有个问题是我们在定义struct中的字段的时候如:Name,Age都是首字母大写的,这样你json序列化的时候才能访问到,如果是小写的,json包则无法访问到,所以就像上述的结果一样,序列化的结果也是首字母大写的,但是我就是想要小写怎么办?这里就用到了tag,将上述的代码更改为如下,序列化的结果就是小写的了:
package main import (
"encoding/json"
"fmt"
) type Student struct {
Name string `json:"name"`
Age int `json:"age"`
} func main() {
var stu Student
stu.Name = "tom"
stu.Age = data, err := json.Marshal(stu)
if err != nil {
fmt.Printf("json marshal fail is %v\n", err)
return
}
fmt.Printf("json marshal result %s\n", data) //反序列化到struct
var stu2 Student
err = json.Unmarshal(data, &stu2)
if err != nil {
fmt.Printf("unmarshal fail is %v\n", err)
return
}
fmt.Printf("unmarshal result is %+v\n", stu2)
}
可以看到将json反序列化成结构的方式是
json.Unmarsha
结构体的比较
如果结构体的全部成员都是可以比较的,那么结构体也是可以比较的,那样的话,两个结构体将可以使用==或!=运算符进行比较。相等比较运算符将比较两个机构体的每个成员
如下面例子:
package main import "fmt" type Pointer struct {
x int
y int
} func main() {
p1 := Pointer{, }
p2 := Pointer{, }
p3 := Pointer{, }
fmt.Printf("p1==p2:%t\n", p1 == p2)
fmt.Printf("p1==p3:%t\n", p1 == p3)
}
匿名字段
结构体中字段可以没有名字
下面是一个简单的例子:
package main import "fmt" type Student struct {
Name string
Age int
int
} func main() {
var stu Student
stu.Name = "tom"
stu.Age =
stu.int =
fmt.Printf("%+v\n", stu)
}
可能上面的这里例子看了之后感觉貌似也没啥用,其实,匿名字段的用处可能更多就是另外一个功能(其他语言叫继承),例子如下:
package main import "fmt" type People struct {
Name string
Age int
}
type Student struct {
People
Score int
} func main() {
var stu Student
// stu.People.Name = "tom"//是下面的简写
// stu.People.Age = 22
stu.Name = "tom"
stu.Age =
stu.Score =
fmt.Printf("%+v\n", stu)
}
注意:关于字段冲突的问题,我们在People中定义了一个Name字段,在Student中再次定义Name,这个时候,我们通过s.Name获取的就是Student定义的Name字段
如下:
package main import "fmt" type People struct {
Name string
Age int
Sex string
}
type Student struct {
//字段冲突,重新定义一个Sex覆盖就行
Sex int //放在People的上边或下边都行
People
} func main() {
var stu Student
stu.Name = "tom"
stu.Age =
stu.Sex =
fmt.Printf("%+v\n", stu)
}
方法
首先强调一下:go中任何自定义类型都可以有方法,不仅仅是struct
注意除了:指针和interface
通过下面简单例子理解:
package main import (
"fmt"
) //这里是我们普通定义的一个函数add
func add(a,b int) int {
return a+b
} type Int int //这里是对Int这个自定义类型定义了一个方法add
func (i Int) add(a,b int) int{
return a+b
}
//如果想要把计算的结果赋值给i
func(j *Int) add2(a,b int){
*j = Int(a+b)
return
} func main(){
c := add(,)
fmt.Println(c)
var b Int
res := b.add(,)
fmt.Println(res) var sum Int
sum.add2(,)
fmt.Println(sum) }
方法的定义:
func(receiver type)methodName(参数列表)(返回值列表){
}
下面是给一个结构体struct定义一个方法
package main import (
"fmt"
) type Student struct{
Name string
Age int
} func (stu *Student)Set(name string,age int){
stu.Name = name
stu.Age = age
} func main(){
var s Student
s.Set("tome",)
fmt.Println(s)
}
注意:方法的访问控制也是通过大小写控制的
在上面这个例子中需要注意一个地方func (stu *Student)Set(name string,age int)这里使用的是(stu *Student)而不是(stu Student)这里其实是基于指针对象的方法
基于指针对象的方法
当调用一个函数时,会对其每个参数值进行拷贝,如果一个函数需要更新一个变量,或者函数的其中一个参数是在太大,我们希望能够避免进行这种默认的拷贝,这种情况下我们就需要用到指针了,所以在上一个代码例子中那样我们需要func (stu *Student)Set(name string,age int)来声明一个方法
这里有一个代码例子:
package main import "fmt" type Pointer struct {
X float64
Y float64
} func (p *Pointer) ScaleBy(f float64) {
p.X *= f
p.Y *= f
} func main() {
//method 1
p1 := &Pointer{, }
p1.ScaleBy()
fmt.Printf("p1:%f\n", *p1) //method 2
p2 := Pointer{, }
p2r2 := &p2
p2r2.ScaleBy()
fmt.Printf("p2:%f\n", p2) //method 3
p3 := Pointer{, }
(&p3).ScaleBy()
fmt.Printf("p3:%f\n", p3) //method 4
//相对来说方法2和方法3有点笨拙
//方法4,go语言这里会自己判断p是一个Point类型的变量,
//并且其方法需要一个Point指针作为指针接收器,直接可以用下面简单的方法
p4 := Pointer{, }
p4.ScaleBy()
fmt.Printf("p4:%f\n", p4)
}
上面例子中最后一种方法,编译器会隐式的帮我们用&p的方法去调用ScaleBy这个方法
当然这种简写方法只适用于变量,包括struct里面的字段,如:p.X
转自https://www.cnblogs.com/zhaof/p/8244542.html
golang之结构体和方法的更多相关文章
- 『GoLang』结构体与方法
结构体 结构体类型 Go 通过结构体的形式支持用户自定义类型,或者叫定制类型. Go 语言结构体是实现自定义类型的一种重要数据类型. 结构体是复合类型(composite types),它由一系列属性 ...
- 六、golang中的结构体和方法、接口
结构体: 1.用来自定义复杂数据结构 2.struct里面可以包含多个字段(属性) 3.struct类型可以定义方法,注意和函数的区分 4.strucr类型是值类型 5.struct类型可以嵌套 6. ...
- Golang 入门 : 结构体(struct)
Go 通过类型别名(alias types)和结构体的形式支持用户自定义类型,或者叫定制类型.试图表示一个现实世界中的实体. 结构体由一系列命名的元素组成,这些元素又被称为字段,每个字段都有一个名称和 ...
- 将c语言的结构体定义变成对应的golang语言的结构体定义,并将golang语言结构体变量的指针传递给c语言,cast C struct to Go struct
https://groups.google.com/forum/#!topic/golang-nuts/JkvR4dQy9t4 https://golang.org/misc/cgo/gmp/gmp. ...
- golang(07)结构体介绍
golang支持面向对象的设计,一般支持面向对象的语言都会有class的设计,但是golang没有class关键字,只有struct结构体.通过结构体达到类的效果,这叫做大成若缺,其用不弊. stru ...
- Go part 5 结构体,方法与接收器
结构体 结构体定义 结构体的定义只是一种内存布局的描述(相当于是一个模板),只有当结构体实例化时,才会真正分配内存空间 结构体是一种复合的基本类型,通过关键字 type 定义为 自定义 类型后,使结构 ...
- go结构体的方法和普通函数
package main import ( "fmt" "math" ) type vertex struct { X, Y float64 } //值接收者是 ...
- go 结构体与方法
go 结构体与方法 go 结构体相当于 python 中类的概念,结构体用来定义复杂的数据结构,存储很多相同的字段属性 结构体的定义 1.结构体的定义以及简单实用 package main imp ...
- go结构体与方法
go结构体相当于python中类的概念 结构体用来定义复杂的数据结构,存储很多相同的字段属性 1.结构体的定义以及简单实用 package main import ( "fmt" ...
随机推荐
- Struts初探(二)
总是找不到对应的action,但别的没用到动态方法调用的都没有问题. 报异常:java.lang.reflect.InvocationTargetException - Class: com.open ...
- Ubuntu 使用Compiz配置炫酷3D桌面
先看一下效果 要实现这种3D 的效果其实很简单. Step 1:安装N卡驱动工具 sudo apt- 这个东西其实没有太大的作用. Step 2:安装Compiz sudo apt-get insta ...
- mysql 给用户赋值权限
解决办法 grant all privileges on *.* to joe@localhost identified by '1'; flush privileges; 拿 joe 1 登陆 附: ...
- python使用pwd和grp操作unix用户及用户组
1.pwd模块 pwd模块提供了一个unix密码数据库即/etc/passwd的操作接口,这个数据库包含本地机器用户帐户信息 常用操作如下: pwd.getpwuid(uid):返回对应uid的示例信 ...
- python---Scrapy模块的使用(二)
出处:http://www.cnblogs.com/wupeiqi/ 一:去除重复URL scrapy默认使用 scrapy.dupefilter.RFPDupeFilter 进行去重,相关配置有: ...
- hdu 1846 Brave Gam
Brave Game http://acm.hdu.edu.cn/showproblem.php?pid=1846 Time Limit: 1000/1000 MS (Java/Others) ...
- 分块+二分 BZOJ 3343
3343: 教主的魔法 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1312 Solved: 585[Submit][Status][Discus ...
- 响应式布局之媒体查询 @media
Media Queries,其作用就是允许添加表达式用以确定媒体的环境情况,以此来应用不同的样式表.换句话说,其允许我们在不改变内容的情况下,改变页面的布局以精确适应不同的设备. 媒体查询有两种玩法, ...
- GlusterFS + lagstash + elasticsearch + kibana 3 + redis日志收集存储系统部署 01
因公司数据安全和分析的需要,故调研了一下 GlusterFS + lagstash + elasticsearch + kibana 3 + redis 整合在一起的日志管理应用: 安装,配置过程,使 ...
- asp.net core 实践
github:https://github.com/zzhi/DotNetWeb 这是一个基于asp.net core web application的练习项目,目的是学习dotnet core新技能 ...