go语言结构体的初始化
未初始化的结构体,成员都是零值 int 0 float 0.0 bool false string nil
func main(){
type Person struct{
in,age int
name,email string
}
var tom Person
fmt.Println(tom)// 0 0 " " " "
}
使用键值对对结构体进行初始化
func main(){
type Person struct {
id,age int
name,email string
}
sk:= Person{
id: 1,
name:"sk",
age: 20,
email: "sk@elysium.org.cn",
}
fmt.Println(sk)//{1,sk, 20, sk@elysium.org.cn}
}
使用值的列表初始化
func main(){
type Person struct{
id,age int
name,email string
}
kite:=Person{
1,
20,
"sk",
"sk@elysium.org.cn"
}
fmt.Println(kite)//{1 20 sk sk@elysium.org.cn}
}
注意:
- 必须初始化结构体的所有字段
- 初始值的填充顺序必须与字段的结构体中的声明顺序一直
- 该方式不能和键值初始化方式混用
部分成员初始化
用不到的成员,可以不进行初始化
func main(){
type Person struct{
id,age int
name,email string
}
kite:=Person{
id:1,
name:"sk"
}
fmt.Println(sk)//{1 0 sk " "}
}
go结构体指针
结构体指针和普通的变量指针相同,先来回顾一下普通变量的指针
func main(){
var name string
name = "Alex"
//p_name 指针类型
var p_name *string
//&name 取name地址
p_name= &name
fmt.Println(name)//tom
//输出指针地址
fmt.Println(p_name)//0xcc00010
//输出指针指向的内容值
fmt.Println(*p_name)//Alex
}
结构体指针
func main(){
type Person struct{
id int
name string
}
var alex = Person{1,"Alex"}
var p_person Person
p_person = &alex
fmt.Println(tom)//{1,alex}
fmt.Println(p_person)//0xc000001313
fmt.Println(*p_person)//{1,Alex}
}
使用new关键字创建结构体指针
我们还可以通过使用new关键词对结构体进行实例化,得到的是结构体的地址,例如:
func main(){
type Person struct{
id int
name string
}
var p_person = new(Person)
fmt.Println(p_person)//*main.Person
}
访问结构体指针成员
访问结构体指针成员,也使用点运算符(.),例如:
func main(){
type Person struct{
id int
name string
}
var p_person = new(Person)
fmt.Println(p_person)//*main.Person
p_person.id=1//等价于*p_person.id
p_person.name="Alex"
fmt.Println(*p_person)//{1,Alex}
}
go结构体作为函数参数
go结构体可以像普通变量一样,作为函数的参数,传递给参数,这里分为两种情况:
- 直接传递结构体,这是一个副本(拷贝),在函数内部不会改变外面结构体内容
- 传递结构体指针,这时在函数内部,能够改变外部结构体内容
直接传递结构体
实例
type Person struct{
id int
name string
}
func showPerson(person Person){
person.id=1
person.name="Alex"
fmt.Println(person)
}
func main(){
person:=Person{1,"Blex"}
fmt.Printf(person)//{1 Blex}
fmt.Println("---------")
showPerson(person){1 Alex}
fmt.Println("---------")
fmt.Println(person)//{1 Alex}
}
从运行结果可以看出,函数内部结构了结构体内容,函数外面并没有被改变。
传递结构体指针
实例
type Person struct{
id int
name string
}
func showPerson(person *Person){
person.id=1
person.name = "Alex"
fmt.Println(person)
}
func main(){
person:=Person{1,"Alex"}
fmt.Println(person)//{1 Alex}
fmt.Println("---------")
showPerson(&person)//{1 Alex}
fmt.Println("---------")
fmt.Prinltn(person)//{1 Alex}
}
从运行结果,我们可以看到,调用函数后,参数被改变了
go嵌套结构体
go语言没有面向对象编程思想,也没用继承关系,但是可以通过结构体嵌套来实现这种效果。
下面通过实例演示如何实现结构体嵌套,加入有一个人Person结构体,这个人还养了一个宠物Dog结构体。
下面我们来看一下:
Dog结构体
type Dog struct{
name string
color string
age int
}
Person结构体
type person struct{
dog Dog
name string
age int
}
访问它们
type Dog struct{
name string
color string
age int
}
type person struct{
dog Dog
name string
age int
}
func main(){
var Alex person
Alex.dog.name = "旺财"
Alex.dog.colo = "富贵"
Alex.dog.age = 2
Alex.name = "tom"
Alex.age = 20
fmt.Println(Alex)//{{旺财 富贵 2} Alex 20}
}
go方法
go语言没有面向对象的特性,也没有类对象的概念。但是,可以使用结构体来模拟这些特性,我们都知道面向对象里面有类方法等概念。
我们也可以声明一些方法,属于某个结构体。
go语言方法的语法
go中的方法,是一种特殊的函数,定义于struct之上(与struct关联,绑定),被称为struct的接收者(receiver)
通俗的讲,方法就是有接收者的函数。
语法的格式如下:
type mytype struct{}
func(recv mytype) my_method(para) return_type{}
func(recv *mytype) my_method(para) return_type{}
mytype:定义一个结构体
recv:接受该方法的结构体(receiver)
my_method:方法名称
para:参数列表
return_type:返回值类型
从语法格式看,一个方法和一个函数非常相似,多了一个接受类型
实例
struct Person struct{
name string
}
func (recv Person) login(name string) bool{
fmt.Println(recv.name)
if recv.name==name{
return true
}else{
return false
}
}
func (rec Person) userName(){
fmt.Println(rec.name)//Alex
}
func main(){
var per= Person{"Alex"}
b:=per.login("Blex")
per.userName()//Alex
fmt.Println(b)//false
}
go语言方法的注意事项
- 方法的receiver type并非一定要
strcut类型,type定义的类型别名,slice,map,channel,func等类型都可以。 struct结合它的方法等价于面向对象中的类。只不过struct可以和它的方法分开,并非一定要属于同一个文件,但必须属于同一个包。- 方法有两种接受类型:
(T Type)和(T *Type),两者有区别。 - 方法就是函数,所有go中没有方法重载(overload)的说法,也就是说同一个类型中的所有方法名必须都唯一。
- 如果receiver是一个指针类型,则会自动解除引用
- 方法和type是分开的,意味着实例的行为(behavior)和数据存储(field)是分开的,但是它们通过receiver建立起关联联系
方法接收者类型
结构体实例,有值类型和指针类型,那么方法的接收者是结构体,那么也有值类型和指针类型。区别就是接收者是非欧复制结构体副本。值类型复制,指针类型不复制。
值类型和指针类型结构体
type Person struct{
name string
}
func main(){
p1:=Person{"tom"}
fmt.Printf("%T",p1)//main.Person 值类型
p2:=&Person{"tom"}
fmt.Printf("%T",p2)//*main.Person 指针类型
}
方法的值类型和指针类型接收者
package main
import "fmt"
type Person struct {
name string
}
func (recv Person) showPerson() {
fmt.Printf("%p\n", &recv)
recv.name = "Alex"
fmt.Println(recv)
}
func (recv *Person) showPersonTwo() {
fmt.Printf("%p\n", recv)
recv.name = "Alex" //等价于*recv.name="Alex"
fmt.Println(*recv)
}
func main() {
var p1 = Person{"Alex"}
fmt.Printf("%p\n", &p1)
p1.showPerson()
fmt.Println(p1)
fmt.Println("-----------")
var p2 = &Person{"Alex"}
fmt.Printf("%p\n", p2)
p2.showPersonTwo()
fmt.Println(*p2)
}
今天就先写到这里了