Golang結構體struct


在這裏插入圖片描述

1. 結構體 struct

1.1 概述

Go語言可以通過自定義的形式形成新的類型,結構體是類型中帶有成員的複合類型,Go語言中使用結構體和結構體成員描述 真實世界 的實體和實體對應的各種屬性 ,通過這個描述體現了Go語言中structclass 具有同等地位

結構體成員 是一系列成員變量 構成的,這些成員變量也被稱爲字段

  • 字段擁有自己的類型和值
  • 一個結構體中字段名必須是唯一的
  • 字段的類型可以是結構體

Go語言中結構體可以擁有方法 並且每種自定義類型都可以擁有自己的方法

Go語言中沒有繼承這樣的面向對象特性,只保留了組合 這個基礎的特性, 組合是形成複合類型的基礎

1.2. 定義結構體

結構體是複合類型,通過type 定義

結構體的定義格式如下:

type 結構體名稱 struct{
    字段1 類型
    字段2 類型
    字段3 類型
    ...
}
  • 結構體名稱 : 標識自定義結構體的名稱 ,在同一包內不能重複
  • struct{} : 標識這是個結構體類型
  • 字段: 表示結構體中的字段名,在一個結構體中字段名必須是唯一
  • 類型: 表示對應的結構體的數據類型,
package main
//定義一個Color的結構體
type Color struct {
	R,G,B byte
}
// 定義一個point 結構體
type Point struct {
	x int64
	y int64
}
// 定義一個Student的結構體
type Student struct {
	name string
	age int
	course []string
	score map[string]int
	average float32
	graduate bool
}
func main(){

}

1.3 實例化結構體

結構體定義只是一種內存佈局的描述,只有當結構體實例化時,纔會真正分配內存,因此只有在結構體實例化之後才能使用結構體中的字段

  • 實例化結構體也是創建一個結構體變量
  • 訪問結構體中的成員變量通過 . 實現
  • 實例化一個結構體,要是沒有復,那麼結構體變量中訪問字段的初始值都是默認值
  • 對同一個結構體實例化出來的多個結構體變量,這些變量個各不相干,結構體是對內存佈局的描述,每次實例化都是結構體變量分配新的內存

結構體本身是一種類型,所以可以以var 關鍵字聲明一個變量是結構體的結構體變量,這樣就完成了實例化

package main

import "fmt"

type Student struct {
	name     string
	age      int
	course   []string
	score    map[string]int
	average  float32
	graduate bool
}

func main() {
	// 實例化方式1
	var stu1  Student
	fmt.Println(stu1)
}


實例化方法2

package main

import "fmt"

type Student struct {
	name     string
	age      int
	course   []string
	score    map[string]int
	average  float32
	graduate bool
}

func main() {
	// 實例化方式2
	var stu2 Student = Student{}
	fmt.Println(stu2)
}

實例化方法3

Go語言中使用new 關鍵字對類型進行實例化,結構體在實例化之後會形成結構體指針

格式:

ins : = new (T)

int *T = new(T)

package main

import "fmt"

type Student struct {
	name     string
	age      int
	course   []string
	score    map[string]int
	average  float32
	graduate bool
}

func main() {
	// 實例化方式1
	var stu3 *Student = new(Student)
	fmt.Println(stu3)
}

go run main.go

&{ 0 [] map[] 0 false}

實例化方法4 ,

格式如下:

int := &T{}

var int * T = &T{}

對結構體進行取地址 & 操作,相當於是進行一次new 的實例化操作 ,得到的是結構體指針

package main

import "fmt"

type Student struct {
	name     string
	age      int
	course   []string
	score    map[string]int
	average  float32
	graduate bool
}

func main() {
	// 實例化方法4
	var stu4 *Student = &Student{}
	fmt.Println(stu4)
}

go run main.go

&{ 0 [] map[] 0 false}

1.4 初始化結構體成員變量

結構體在實例化時,或者之後都可以對其成員變量進行初始化

package main

import "fmt"

type Student struct {
	name     string
	age      int
	course   []string
	score    map[string]int
	average  float32
	graduate bool
}

func main() {
	var stu1  Student
	// 結構體變量成員初始化1 訪問結構體字段方式賦值
	stu1.name = "張三"
	stu1.age = 70
	// slice 和 map 都需要make之後才能使用
	stu1.course = make([]string,3)
	stu1.course[0] = "數學"
	stu1.course[1] = "物理"
	stu1.course[2] = "化學"
	fmt.Println(stu1)
	// 結構體變量成員初始化2 鍵值對形式賦值
	var stu2 Student = Student{
		name:"李四",
		age:70,
		course:[]string{"語文","地理"},
		score: map[string]int{"語文":120,"地理":90},
		average:105.0,
		graduate:false,
	}
	fmt.Println(stu2)
	// 結構體變量成員初始化3 值列表形式賦值
	stu3 := Student{
		"王五",
		70,
		[]string{"音樂","美術"},
		map[string]int{"音樂":90,"美術":80},
		85.0,
		true,
	}
	fmt.Println(stu3)
}

go run main.go

{張三 70 [數學 物理 化學] map[] 0 false}
{李四 70 [語文 地理] map[地理:90 語文:120] 105 false}
{王五 70 [音樂 美術] map[美術:80 音樂:90] 85 true}

看一訪問結構體成員的例子

結構體指針訪問結構體成員的標準格式是 (*結構體指針).字段名 ,例如下面的例子 (*stu).name = "趙六"

但是在go語言中也支持 結構體.字段名 如下 stu.name = "秦七" 的形式,這是因爲go語言自己做了一個簡化,Go在編譯時將 stu.name 轉化成了 (*stu).name

package main

import "fmt"

type Student struct {
	name     string
	age      int
	course   []string
	score    map[string]int
	average  float32
	graduate bool
}
func main() {
	var stu *Student = new(Student)
	fmt.Println(stu)
	// 結構體變量stu是結構體指針那麼訪問結構體成員
	(*stu).name = "趙六"
	fmt.Println(*stu)
	// 一般的方法訪問結構體成員變量
    stu.name = "秦七" // (*stu).name = "秦七"
	fmt.Println(*stu)
}

go run main.go

&{ 0 [] map[] 0 false}
{趙六 0 [] map[] 0 false}
{秦七 0 [] map[] 0 false}

1.5 結構體變量複製

結構體變量作爲值賦給另外的變量是值拷貝,那麼這兩個結構體變量沒有任何關係

結構體變量也可以將結構體地址賦值給結構體指針變量,這樣就成了地址拷貝

package main

import "fmt"

type Person struct {
	name string
	age  int
}

func main() {
	var p1 Person = Person{"張三", 70}
	// 結構體值拷貝
	p2  := p1
	p2.name = "李四"
	fmt.Printf("p1 =>addr = %p,value = %v\n", &p1, p1)
	fmt.Printf("p2 =>addr = %p,value = %v\n", &p2, p2)
	// 結構體地址拷貝
	var p3 *Person = &p2
	// p3的修改,直接影響p2
	p3.name = "王五"
	fmt.Printf("p2 =>addr = %p,value = %v\n", &p2, p2)
	// p3的值就是p2 的地址,當然p3也有自己的內存地址
	fmt.Printf("p3 =>addr = %p,p3 = value = %p\n", &p3, p3)

}

go run main.go

p1 =>addr = 0xc00004a420,value = {張三 70}
p2 =>addr = 0xc00004a440,value = {李四 70}
p2 =>addr = 0xc00004a440,value = {王五 70}
p3 =>addr = 0xc000080020,p3 = value = 0xc00004a440

1.6 匿名結構體

匿名結構體就是沒有結構體名稱的結構體,無需type關鍵字就可以直接使用

使用的不多,此處只是提一下

定義格式和初始化寫法

ins := struct{
    字段名1 類型1
    字段名2 類型2
    字段名3 類型3
    ...
}{
    字段名1 :1,
    字段名2 :2,
    字段值3 :3,
    ...
}
package main

import "fmt"

func getType(ins struct {
	id   int
	data string
}) {
	fmt.Printf("%T\n", ins)
	ins.id = 99
	fmt.Println(ins)
}
func main() {
	ins := struct {
		id   int
		data string
	}{
		1,
		"hello golang",
	}
	// 將結構體當做值賦給另外一個變量,值拷貝
	ins2 := ins
	ins2.id = 2
	ins2.data = "hello world"
	getType(ins)
	getType(ins2)
	fmt.Println(ins)
	fmt.Printf("%T\n", ins)
}

go run main.go

struct { id int; data string }
{99 hello golang}
struct { id int; data string }
{99 hello world}
{1 hello golang}
struct { id int; data string }

1.7 模擬構造函數

Go語言中沒有進行顯示初始化的值都會使用它自身的默認值,結構體也是如此.Go語言中沒有其他編程語言中的構造函數 這個概念,那麼結構體的初始化工作可以交給一個全局的構建函數函數來完成,模擬出構造函數

package main

import "fmt"

type Person struct {
	name        string
	nationality string
	BloodType   byte
}

func NewPerson(name string, nationality string, blood byte) *Person {
	return &Person{
		name:        name,
		nationality: nationality,
		BloodType:   blood,
	}
}
func main() {
	p1 := NewPerson("張三", "漢族", 'A')
	fmt.Printf("%s 是 %s 血型是%c型\n", p1.name, p1.nationality, p1.BloodType)
	p2 := NewPerson("李四", "滿族", 'B')
	fmt.Printf("%s 是 %s 血型是%c型", p2.name, p2.nationality, p2.BloodType)
}

go run main.go

張三 是 漢族 血型是A型
李四 是 滿族 血型是B型
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章