Golang - struct


定義

  • 理解爲"類"
  • 值類型

示例

package main

import "fmt"

// struct 定義結構體, 類似python中的類, 值類型
type student struct { // 首字母大寫才外部可見
	name  string
	age   int
	score int
}

// 構造函數, 這裏實際上和結構體沒有關係, 只是通過函數實例化一個結構體 
func newStudent(name string, age, score int) *student {
	return &student{
		name:  name,
		age:   age,
		score: score, // 逗號必不可少
	}
}

// 結構體的方法, 需要用 (s *stu) 聲明瞭接收的結構體, s爲約定俗稱的寫法
func (s *stu) printScore() {
	fmt.Println(s.score)
}

func main() {
	// 實例化
	stu1 := newStu("Tim", 18, 100)

	// 取值
	fmt.Println(stu1.name, stu1.age, stu1.score)

	// 調用結構體方法
	stu1.printScore()
}


實例化的幾種寫法

package main

import "fmt"

type stu struct {
	name  string
	age   int
	score int

func main() {
	// 方法 1
	p1 := stu{} // 沒有賦值, 結構體內所有的值都爲零值
	fmt.Println(p1)

	// 方法 2
	p2 := new(stu)
	// 方法 3
	p3 := &stu{}
	fmt.Println(p2, p3) // 得到的都是指針

	// 值類型: 初始化 = 實例化+賦值
	stu2 := stu{
		name:  "a",
		score: 100, // 由於聲明瞭 key, 所以可以不按順序
		age:   18,
	}
	fmt.Println(stu2)

	stu3 := stu{
		"a",
		19,
		120,
	}
	fmt.Println(stu3)
}


指針接收者和值接收者

  • 當需要修改結構體內部屬性的時候, 方法使用指針接收者
  • 只需要取值的之後, 方法可以使用值接收者
package main

import "fmt"

type stu struct {
	name  string
	score int
}

// 值接收者, 適用於單純取值
func (s stu) getScore() {
	fmt.Println(s.score)
}

// 指針接收者, 適用於需要修改結構體的內部屬性時使用
func (s *stu) setScore(newScore int) {
	s.score = newScore
}

func main() {
	stu1 := stu{name: "Tim", score: 100}

	// 得到成績
	stu1.getScore()

	// 更改成績
	stu1.setScore(99)
	fmt.Println(stu1.score)
}


結構體的其他用法

嵌套結構體

package main

import "fmt"

type address struct {
	country string
	city    string
}

type person struct {
	name string
	age  int
	addr address
}

func main() {
	p1 := person{
		name: "Tim",
		age:  22,
		addr: address{
			country: "中國",
			city:    "北京",
		},
	}

	fmt.Println(p1.addr.city) // 必須一層一層找
}


嵌套匿名結構體

package main

import "fmt"

type address struct {
	country string
	city    string
}

type person struct {
	name string
	age  int
	address
}

func main() {
	p1 := person{
		name: "Tim",
		age:  22,
		address: address{
			country: "中國",
			city:    "北京",
		},
	}

	// 可以使用完整的, 也可以使用簡寫
	fmt.Println(p1.address.city)
	fmt.Println(p1.city) // city 在上一層必須沒有
}


結構體的繼承

package main

import "fmt"

// animal 結構體
type animal struct {
	name string
}

// 結構體方法
func (a animal) sayHi() {
	fmt.Println("動物")
}

// bird 結構體
type bird struct {
	fly bool
	// 這樣就表示繼承了 animal 的屬性和方法
	animal
}

// 結構體方法
func (b bird) sayHi() {
	fmt.Println("鳥類")
}

func main() {
	bee := bird{
		fly: true,
		animal: animal{
			name: "大黃蜂",
		},
	}

	// 若方法名相同要進到對應類中執行
	bee.sayHi()
	bee.animal.sayHi()
}


匿名結構體

package main

// 並不推薦的一種寫法

import "fmt"

type cat struct {
	name string
	int // 未聲明屬性名, 只聲明瞭類型, 這種沒有屬性名的類型不可重複出現
	bool
}

func main() {
	c1 := cat{name: "Tim", int: 3, bool: true}

	fmt.Println(c1)
}


證明: 結構體中屬性的內存佈局

package main

import "fmt"

// 結構體佔用連續內存空間
func main() {
	type test struct {
		a int16
		b int16
		c int16
	}
	var t = test{
		a: 1,
		b: 2,
		c: 3,
	}
	fmt.Println(&(t.a)) // 0xc000096000
	fmt.Println(&(t.b)) // 0xc000096001
	fmt.Println(&(t.c)) // 0xc000096002
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章