Go语言学习之旅--结构体


在定义结构体之前,我们先来看看什么是类型定义和类型别名

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)
}

  • 使用值的列表初始化

注意:

  1. 必须初始化结构体的所有字段。
  2. 初始值的填充顺序必须与字段在结构体中的声明顺序一致。
  3. 该方式不能和键值初始化方式混用。
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写的,如有不对可以评论留言

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值