Golang语言学习从入门到实战----结构体以及内存分布

1.Golang语言面向对象编程说明

  • Golang也支持面向对象编程(OOP),但是和传统的面向对象编程有区别,并不是纯粹的面向对象语言。所以我们说Golang支持面向对象编程特性是比较准确的。
  • Golang没有(class),Go语言的结构体(struct)和其它编程语言的类(class)有同等的地位,你可以理解Golang是基于struct来实现OOP特性的。
  • Golang面向对象编程非常简洁,去掉了传统OOP语言的继承、方法重载、构造函数和析构函数、隐藏的this指针等等
  • Golang仍然有面向对象编程的继承,封装和多态的特性,只是实现的方式和其它OOP语言不一样,比如继承:Golang没有extends关键字,继承是通过匿名字段来实现。
  • Golang面向对象(OOP)很优雅,OOP本身就是语言类型系统(typesystem)的一部分,通过接口interface关联,耦合性低,也非常灵活。后面同学们会充分体会到这个特点。也就是说在Golang中面向接口编程是非常重要的特性

1.1 Golang中的struct

  1. 用来自定义复杂的数据结构

  2. struct里面可以包含多个字段(属性)

  3. struct类型可以定义方法, 注意和函数的区分

  4. struct类型是值类型

  5. struct类型可以嵌套

  6. Go语言中没有class类型,只有struct类型

1.2 struct的定义

  1. struct 声明:
type 标识符 struct{
	field1 type
	field2 type
}

例子:

type Student struct{
	Name  string
	Age   int
	Score int
}
  1. 字段/属性
  • 结构体字段=属性=field

  • 字段是结构体的一个组成部分,一般是基本数据类型、数组,也可是引用类型。

  • 字段声明语法同变量,示例:字段名字段类型

  • 字段的类型可以为:基本类型、数组或引用类型

  • 在创建一个结构体变量后,如果没有给字段赋值,都对应一个零值(默认值),规则同前面讲的一样:布尔类型是false,数值是0,字符串是""。

  • 数组类型的默认值和它的元素类型相关,比如score[3] int则为[0,0,0]指针,slice,和map的零值都是nil,即还没有分配

package main

import "fmt"

type Person struct {
	Name   string
	Age    int
	Scores [5]float64
	ptr    *int              // 指针
	slice  []int             // 切片
	map1   map[string]string // map
}

func main() {

	// 定义结构体变量
	var p1 Person
	fmt.Println(p1)

	if p1.ptr == nil {
		fmt.Println("ok1")
	}

	if p1.slice == nil {
		fmt.Println("ok2")
	}

	if p1.map1 == nil {
		fmt.Println("ok3")
	}

	p1.slice = make([]int, 10)
	p1.slice[0] = 100

	p1.map1 = make(map[string]string)
	p1.map1["key1"] = "tom"

	fmt.Println(p1)
}

输出:

{ 0 [0 0 0 0 0] <nil> [] map[]}
ok1
ok2
ok3
{ 0 [0 0 0 0 0] <nil> [100 0 0 0 0 0 0 0 0 0] map[key1:tom]}
  1. 不同结构体变量的字段是独立,互不影响,

一个结构体变量字段的更改,不影响另外一个,结构体是值类型

package main

import "fmt"

type Monster struct {
	Name string
	Age int
}

func main() {
	// 不同结构体变量的字段是独立,互不影响 
	// 一个结构体变量字段的更改,不会影响下一个
	var monster_one Monster
	var monster_two Monster

	monster_one.Name = "牛"
	monster_one.Age = 123

	monster_two.Name = "猴"
	monster_two.Age = 143

	fmt.Println("monster_one=", monster_one)
	fmt.Println("monster_two=", monster_two)

}

输出:

monster_one= {123}
monster_two= {143}
  1. 创建结构体变量和访问结构体字段

方式1-直接声明var person Person

方式2-{} var person Person = Person{}

方式3-& varperson*Person=new(Person)

方式4-{} var person *Person = &Person{}

说明:

  • 第3种和第4种方式返回的是结构体指针
  • 结构体指针访问字段的标准方式应该是:(*结构体指针).字段名,比如(*person).Name = "tom"
  • go做了一个简化,也支持结构体指针.字段名,比如person.Name="tom"
  • 这更加符合程序员使用的习惯,go编译器底层对person.Name做了转(*person).Name。
  1. struct类型的内存分配机制
package main

import "fmt"

type Person struct {
	Name string
	Age int
}
func main() {
	var p1 Person

	p1.Age = 10
	p1.Name = "小明"
	var p2 Person = p1

	fmt.Println(p2.Age)

	p2.Name = "tom"

	fmt.Printf("p2.Name=%v p1.Name=%v", p2.Name, p1.Name)
}

10
p2.Name=tom p1.Name=小明

内存图:
Golang语言学习从入门到实战----结构体以及内存分布_第1张图片

package main

import "fmt"

type Person struct {
	Name string
	Age int
}
func main() {
	var p1 Person
	p1.Age = 10
	p1.Name = "小明"

	var p2 *Person = &p1

	fmt.Println((*p2).Age)
	fmt.Println(p2.Age)

	p2.Name = "小红"
	fmt.Printf("p2.Name=%v p1.Name=%v \n", p2.Name, p1.Name)
	fmt.Printf("p2.Name=%v p1.Name=%v \n", (*p2).Name, p1.Name)

	fmt.Printf("p1的地址%p\n", &p1)
	fmt.Printf("p2的地址%p p2的值%p", &p2,p2)

}

输出:

10
10
p2.Name=小红 p1.Name=小红 
p2.Name=小红 p1.Name=小红 
p1的地址0xc0000044c0
p2的地址0xc000006028 p2的值0xc0000044c0

内存图:
Golang语言学习从入门到实战----结构体以及内存分布_第2张图片

你可能感兴趣的:(Golang)