10 结构

结构

  1. Go 中的struct与C中的struct非常类似,并且Go没有class
  2. 使用Type(Name) struct{}定义结构,名称遵循可见性规则
  3. 支持指向自身的指针类型成员
  4. 支持匿名结构,可用作成员或者定义成员变量
  5. 匿名结构也可以用于map的值
  6. 可以使用字面值对结构进行初始化
  7. 允许直接通过指针来读写结构成员
  8. 相同类型的成员可以直接拷贝赋值
  9. 支持== 与 != 比较运算符,但不支持>或<
  10. 支持匿名字段,本质是定义了以某个类型名为名称的字段
  11. 嵌入结构作为匿名字段看起来像继承,但不是继承
  12. 可以使用匿名字段指针

struct的简单使用

我们先定义一个struct,然后在main函数里面使用它即可

type test struct {
	Name string
	Age  int
}

func main() {
	a := test{}
	a.Name = "Leo"  // 对Name这个进行赋值
	a.Age = 22   // 对Age这个变量进行赋值
	a := test{   // 也可以这样进行简单初始化,初始化的格式如下:
		Name: "Leo ",    // 变量名:  值, 
	}
	fmt.Println(a)
}
struct 多层嵌套

所谓的多层嵌套就是struct里面再包含了一个struct,代码如下所示:

type person struct {
	Name    string
	Age     int
	contact struct {  // struct里面再包含了一个struct
		Phone, City string
	}
}

func main() {
	a := person{Name: "joe", Age: 19}
	a.contact.Phone = "182165234545"  // 给里面那层struct赋值的时候只能这样做
	a.contact.City = "Beijing"
	fmt.Println(a)
}
struct 内存地址的拷贝
package main

import (
	"fmt"
)

type test struct {
	Name string
	Age  int
}

func main() {
	a := test{
		Name: "Leo ",
	}
	a.Age = 22
	A(a)
	fmt.Println(a)  // 此时打印出来的结果还是22
}

func A(per test) {
	per.Age = 19
	fmt.Println("A", per)
}
// 打印结果如下:
A {Leo  19}   // 值已经发生改变
{Leo  22} // 值没有发生改变

从上面的例子能够看出来,这个函数A的修改并没有影响main方法里面的值,所以可以得出这个修改实际上是test的一个内存拷贝,如果真正想在A里面修改值后影响到 main里面的值,就需要把内存地址传给A,那么就应该这么做,代码如下:

func main() {
	a := test{
		Name: "Leo ",
	}
	a.Age = 22
	A(&a)  // 加上&符合把内存地址传入
	fmt.Println(a)
}

func A(per *test) {  // 加上一个*号在test之前
	per.Age = 19
	fmt.Println("A", per)
}

那么问题来了,如果我有多个方法需要传入内存地址,那么该如何一次性让a等于内存地址呢?请看下面的代码

func main() {
	a := &test{   // 提前把&放入到test之前
		Name: "Leo ",
	}
	a.Age = 22
	A(a)
	B(a)
	fmt.Println(a)
}

func A(per *test) {  // 每个方法 的test前面添加一个*即可
	per.Age = 19
	fmt.Println("A", per)
}

func B(per *test) {  // 每个方法 的test前面添加一个*即可
	per.Age = 90
	fmt.Println("B", per)
}

struct 匿名结构

匿名结构 的写法和js的自执行函数差不多,go的写法是 struct{}{}

func main() {
	a := struct {
		Name string
		Age  int
	}{
		Name: "joe",
		Age:  19,
	}
	fmt.Println(a)
}

匿名结构

struct里面没有写变量名,只写了类型,所以赋值的时候只能照着顺序来

type person struct {
	string
	int
}
func main() {
	a := person{"joe", 19}
	fmt.Println(a)
}

struct 比较

两个struct之间比较的话,struct名字必须一样,如下所示

func main() {
	a := person{"joe", 19}
	b := person{"joe", 22}
	fmt.Println(a == b)  // 两个struct的名字一样才行
}

在struct继承情况下,如果有同名的变量会发生什么情况

话不多说,直接看代码:

import (
	"fmt"
)

type human struct {
	student
	Name string
}

type student struct {
	Name string
}

func main() {
	b := human{Name: "hehe", student: student{Name: "Leo"}} // 变量同名了
	fmt.Println(b.Name, b.student.Name)
}
// 打印结果
hehe Leo

由打印结果为导向,可以看出来,即使在继承struct的情况,有同名的也不会互相影响。

在struct继承情况下,父类没有的变量名而子类有会发生什么情况

话不多说,请看代码

import (
	"fmt"
)

type human struct {
	student
}

type student struct {
	Name string
}

func main() {
	b := human{student{Name: "Leo"}}
	fmt.Println(b.Name, b.student.Name)
}
// 打印结果
Leo Leo

由打印结果为导向,可以看出来,如果父struct没有name的话,那么就会从子struct上取值

posted @ 2017-05-08 22:29  温柔易淡  阅读(203)  评论(0编辑  收藏  举报