结构体
在定义结构体之前,我们先来看看什么是类型定义和类型别名
go语言类型定义
类型定义的语法
type NewType Type
举例
func main() {
//类型定义
type MyInt int
//i为MyInt类型
var i MyInt
i = 100
fmt.Printf("i: %v i: %T\n", i, i)
}
go语言类型别名
类型别名语法
type NewType = Type
举例
func main() {
//类型别名定义
type MyInt2 = int
//i还是int类型
var i MyInt2
i = 100
fmt.Printf("i: %v i: %T\n", i, i)
}
go语言类型定义和类型别名的区别
- 1.类型定义相当于定义了一个全新的类型,与之前的类型不同;但是类型别名并没有定义一个新的类型,而是使用一个别名来替换之前的类型
- 2.类型别名只会在代码中存在,在编译完成之后并不会存在该别名
- 3.因为类型别名和原来的类型是一致的,所以原来类型所拥有的方法,类型别名中也可以调用,但是如果是重新定义的一个类型,那么不可以调用之前的任何方法
结构体
go语言结构体的定义
结构体的定义和类型定义类似,只不过多了一个struct关键字
- 语法结构如下:
type struct_variable_type struct {
member definition;
member definition;
...
member definition;
}
- type:结构体定义关键字
- struct_variable_type:结构体类型名称
- struct:结构体定义关键字
- member definition:成员定义
举例
下面我们定义一个人的结构体Person
type Person struct {
id int
name string
age int
email string
}
以上我们定义一个Person结构体,有四个成员,来描述一个Person的信息。类型相同可以合并到一行,例如:
type Person struct {
id, age int
name, email string
}
声明一个结构体变量
声明一个结构体变量和声明一个普通变量相同,例如:
var tom Person
fmt.Printf("tom: %v\n", tom)
kite := Person{}
fmt.Printf("kite: %v\n", kite)
结果
tom: {0 0 }
kite: {0 0 }
结构体成员,在没有赋值之前都是零值。
结构体的初始化
- 未初始化的结构体
成员都是默认值 int 0 float 0.0 bool false string nil nil
package main
import "fmt"
func main() {
type Person struct {
id, age int
name, email string
}
var tom Person
fmt.Printf("tom: %v\n", tom)
}
- 使用键值对对结构体进行初始化
package main
import "fmt"
func main() {
type Person struct {
id, age int
name, email string
}
kite := Person{
id: 1,
name: "kite",
age: 20,
email: "zjc.com",
}
fmt.Printf("kite: %v\n", kite)
}
- 使用值的列表初始化
注意:
- 必须初始化结构体的所有字段。
- 初始值的填充顺序必须与字段在结构体中的声明顺序一致。
- 该方式不能和键值初始化方式混用。
package main
import "fmt"
func main() {
type Person struct {
id, age int
name, email string
}
kite := Person{
1,
20,
"kite",
"zjc.com",
}
fmt.Printf("kite: %v\n", kite)
}
- 部分成员初始化
package main
import "fmt"
func main() {
type Person struct {
id, age int
name, email string
}
kite := Person{
id: 1,
name: "kite",
}
fmt.Printf("kite: %v\n", kite)
}
访问结构体成员
可以使用点运算符(.),来访问结构体成员,例如:
package main
import "fmt"
func main() {
type Person struct {
id, age int
name, email string
}
var tom Person
tom.id = 1
tom.name = "tom"
tom.age = 20
tom.email = "zjc.com"
fmt.Printf("tom: %v\n", tom)
}
匿名结构体
如果结构体是临时使用,可以不用起名字,直接使用,例如:
package main
import "fmt"
func main() {
var dog struct {
id int
name string
}
dog.id = 1
dog.name = "旺财"
fmt.Printf("dog: %v\n", dog)
}
结构体指针
举例
package main
import "fmt"
func main() {
type Person struct {
id int
name string
}
var tom = Person{1, "tom"}
var p_person *Person
p_person = &tom
fmt.Printf("tom: %v\n", tom)
fmt.Printf("p_person: %p\n", p_person)
fmt.Printf("*p_person: %v\n", *p_person)
}
使用new
关键字创建结构体指针
我们还可以通过使用new关键字对结构体进行实例化,得到的是结构体的地址,例如:
package main
import "fmt"
func main() {
type Person struct {
id int
name string
}
var p_person = new(Person)
fmt.Printf("p_person: %T\n", p_person)
}
访问结构体指针成员
访问结构体指针成员,也使用点运算符(.),例如:
package main
import "fmt"
func main() {
type Person struct {
id int
name string
}
var p_person = new(Person)
fmt.Printf("p_person: %T\n", p_person)
p_person.id = 1
p_person.name = "tom"
fmt.Printf("*p_person: %v\n", *p_person)
}
结构体作为函数参数
定义
go结构体可以像普通变量一样,作为函数的参数,传递给函数,这里分为两种情况:
- 直接传递结构体,这是是一个副本(拷贝),在函数内部不会改变外面结构体内容。
- 传递结构体指针,这时在函数内部,能够改变外部结构体内容。
直接传递结构体
package main
import "fmt"
type Person struct {
id int
name string
}
func showPerson(person Person) {
person.id = 1
person.name = "kite"
fmt.Printf("person: %v\n", person)
}
func main() {
person := Person{1, "tom"}
fmt.Printf("person: %v\n", person)
fmt.Println("----------------")
showPerson(person)
fmt.Println("----------------")
fmt.Printf("person: %v\n", person)
}
运行结果:
person: {1 tom}
----------------
person: {1 kite}
----------------
person: {1 tom}
从运行结果可以看出,函数内部改变了结构体内容,函数外面并没有被改变。
传递结构体指针
package main
import "fmt"
type Person struct {
id int
name string
}
func showPerson(person *Person) {
person.id = 1
person.name = "kite"
fmt.Printf("person: %v\n", person)
}
func main() {
person := Person{1, "tom"}
fmt.Printf("person: %v\n", person)
fmt.Println("----------------")
showPerson(&person)
fmt.Println("----------------")
fmt.Printf("person: %v\n", person)
}
运行结果
person: {1 tom}
----------------
person: &{1 kite}
----------------
person: {1 kite}
从运行结果,我们可以看到,调用函数后,参数被改变了。
嵌套结构体
go语言没有面向对象编程思想,也没有继承关系,但是可以通过结构体嵌套来实现这种效果。
下面通过实例演示如何实现结构体嵌套,加入有一个人Person结构体,这个人还养了一个宠物Dog结构体。
下面我们来看一下:
Dog结构体
type Dog struct {
name string
color string
age int
}
Person结构体
type person struct {
dog Dog
name string
age int
}
package main
import "fmt"
type Dog struct {
name string
color string
age int
}
type person struct {
dog Dog
name string
age int
}
访问它们
func main() {
var tom person
tom.dog.name = "花花"
tom.dog.color = "黑白花"
tom.dog.age = 2
tom.name = "tom"
tom.age = 20
fmt.Printf("tom: %v\n", tom)
}
运行结果
tom: {{花花 黑白花 2} tom 20}
golang继承
golang本质上没有oop的概念,也没有继承的概念,但是可以通过结构体嵌套实现这个特性。
package main
import "fmt"
type Animal struct {
name string
age int
}
func (a Animal) eat() {
fmt.Println("eat...")
}
func (a Animal) sleep() {
fmt.Println("sleep")
}
type Dog struct {
Animal
}
type Cat struct {
Animal
}
func main() {
dog := Dog{
Animal{
name: "dog",
age: 2,
},
}
cat := Cat{
Animal{name: "cat",
age: 3},
}
dog.eat()
dog.sleep()
cat.eat()
cat.sleep()
}
golang构造函数
golang没有构造函数的概念,可以使用函数来模拟构造函数的的功能。
例如
package main
import "fmt"
type Person struct {
name string
age int
}
func NewPerson(name string, age int) (*Person, error) {
if name == "" {
return nil, fmt.Errorf("name 不能为空")
}
if age < 0 {
return nil, fmt.Errorf("age 不能小于0")
}
return &Person{name: name, age: age}, nil
}
func main() {
person, err := NewPerson("tom", 20)
if err == nil {
fmt.Printf("person: %v\n", *person)
}
}
本篇文章借鉴https://blog.csdn.net/geek99_guo/article/details/121752993?spm=1001.2014.3001.5502写的,如有不对可以评论留言