1. 程式人生 > >Go基礎之面向物件(結構體與方法篇)

Go基礎之面向物件(結構體與方法篇)

  • go語言的面向物件相對簡單,只支援封裝,不支援繼承和多型,go中用面向介面來做繼承和多型的任務
  • go中沒有class ,只有struct
  • struct的建立

type treeNode struct {
    value int
    left, right *treeNode
}

  • struct的宣告和初始化

//宣告一個結構體型別
    var root treeNode
    
    //初始化方式一
    root = treeNode{value:3}


    //初始化方式二
    root.left = &treeNode{}
    root.right = &treeNode{5,nil,nil}


    //初始化方式三
    root.right.left = new(treeNode)   
    //new(),只接受一個引數,這個引數是一個型別,分配好記憶體後,返回一個指向該型別記憶體地址的指標。同時請注意它同時把分配的記憶體置為零,也就是型別的零值。
    //這裡,root結構本身,而root.left是一個地址,在go中不論地址含是結構本身,一律用"."來訪問成員,  而C++中,訪問地址的成員要用"->"


    //初始化方法四 使用工廠方法
    root.right.right = creatNode(4) 
    
    nodes := []treeNode{
        {value:3},          //這裡相當於 treeNode{value:3}, 前面的treeNode省略掉了


        {},
        {6,nil,&root},
    }    
    fmt.Println(nodes)   //輸出結果: [{3 <nil> <nil>} {0 <nil> <nil>} {6 <nil> 0xc420090020}] 

  • struct的工廠化方法,go的結構體沒有建構函式一說,但我們可以給我們定義的結構體建立一個工廠方法,用來初始化結構體
  • 工廠方法返回了一個區域性變數地址

func creatNode(value int) *treeNode {
    return &treeNode{value: value}
    //這裡,treeNode{value: value}是定義在函式中的,若在C++中,它是一個區域性變數,是不能返回到外面給別人使用的,但在go中,區域性變數可以返回出去給別人使用


  • 為struct建立方法,"func"後可以跟一個接受者,其實這個接受者實質上也是函式的一個引數,只是呼叫的時候會有些區別

func (node treeNode) print() {
    fmt.Println(node.value)
}
其和 

func print(node treeNode) {
         fmt.Println(node.value)
 }
本質上實現的作用一樣
但前者的呼叫: print(root)
後者的呼叫:  root.print() 

  • struct方法接收者的值傳遞和指標傳遞:
  • 結構體方法的接受者,同樣是傳值的,想要傳遞引用,則宣告為指標型別
  • 只有將接受者設為指標,才可改變結構體的內容

func (node treeNode) setValue1 (value int){  //接收者為值傳遞
    node.value = value
}


func (node *treeNode) setValue2 (value int){  //接收者為指標傳遞
    node.value = value
    //這裡的node是一個指標型別,是一個地址,go中地址也可以通過"."來直接訪問其地址所存內容的成員,而不需(*node).value 或 node->value
}

結果驗證:

root.right.left.print()      //輸出結果:0
root.right.left.setValue1(10)
root.right.left.print()    //輸出結果:0  setValue1()為值傳遞,value沒有被改掉
    
root.right.left.setValue2(20)
root.right.left.print()     //輸出結果:20  setValue2()引用傳遞,value被改掉

//注意:這裡在呼叫的時候,會進行人性化處理,接受者是結構指標型別或者是實際的結構型別,呼叫者是結構指標或實際結構體,不管如何組合都是可以混用的
 (*root.right.left).print()     //輸出結果:20 與 root.right.left.print() 一致

  • go中struct的接收者為nil指標時也可以呼叫方法
  • go中的nil與其他語言中的null不同,null只是用來判斷是不是空

func (node *treeNode) setValue3 (value int){
    if node == nil{
        fmt.Println("setting value to nil node!")
        return
    }
    node.value = value

結果驗證:

var pRoot *treeNode
pRoot.setValue3(30)     //輸出結果:setting value to nil node!
//這裡的pRoot 只有宣告 是一個nil指標,但它同樣可以呼叫setValue3()

  • 值接收者VS指標接受者
  1. 要改變內容必須使用指標接收者
  2. 結構過大也考略使用指標接受者
  3. 一致性:如有指標接受者,最好都是指標接收者
  4. 值接收者是go語言特有的,其他語言都有指標接收者(Java中的this)
  5. 值/指標接收者均可接收值/指標 
     
  • struct是建立在堆上還是棧上?
  1. c++中,區域性變數是分配在棧上的,函式一退出,區域性變數會立刻被銷燬,若想要傳出去,必須在堆上分配,堆上分配的要手動釋放
  2. Java中多使用new(),使用new()是分配在堆上的,需要有垃圾回收機制
  3. go中,不需要知道結構建立在哪裡,go語言的編譯器以及執行環境會根據需要自動檢測結構需要建立在哪裡,go中存在垃圾回收器,堆上分配的內容會參與垃圾回收 
     
  • 樹的中序遍歷 

//構造一棵樹` 

var root treeNode
    root = treeNode{value:3}
    root.left = &treeNode{}
    root.right = &treeNode{5,nil,nil}
    root.right.left = new(treeNode)   
    root.right.right = creatNode(4)  

//中序遍歷整棵樹  左-中-右的順序
func (node *treeNode) traverse(){
    if node == nil{
        return
    }
    node.left.traverse()
    node.print()
    node.right.traverse()

完整程式碼:

package main

import (
	"fmt"
)

type treeNode struct {
	value int
	left, right *treeNode
}


//go的結構體沒有建構函式一說,但我們可以建立一個工廠方法給我們定義的結構體
//工廠方法返回了一個區域性變數地址
func creatNode(value int) *treeNode {
	return &treeNode{value: value}
	//這裡,treeNode{value: value}是定義在函式中的,若在C++中,它是一個區域性變數,是不能返回到外面給別人使用的,但在go中,區域性變數可以返回出去給別人使用
}



//為結構體建立方法,"func"後可以跟一個接受者,其實這個接受者實質上也是函式的一個引數,只是呼叫的時候會有些區別
func (node treeNode) print() {
	fmt.Println(node.value)
}
//其和 func print(node treeNode) {
//     	fmt.Println(node.value)
//     }
//本質上實現的作用一樣
//但前者的呼叫: print(root)
//後者的呼叫:  root.print()

//結構體方法的接受者,同樣是傳值的,想要傳遞引用,則宣告為指標型別
//只有將接受者設為指標,才可改變結構體的內容
func (node treeNode) setValue1 (value int){
	node.value = value
}
func (node *treeNode) setValue2 (value int){
	node.value = value
	//這裡的node是一個指標型別,是一個地址,go中地址也可以通過"."來直接訪問其地址所存內容的成員,而不需(*node).value 或 node->value
}

//nil指標也可以呼叫方法
//go中的nil與其他語言中的null不同,null只是用來判斷是不是空
func (node *treeNode) setValue3 (value int){
	if node == nil{
		fmt.Println("setting value to nil node!")
		return
	}
	node.value = value
}


//中序遍歷整棵樹  左-中-右的順序
func (node *treeNode) traverse(){
	if node == nil{
		return
	}
	node.left.traverse()
	node.print()
	node.right.traverse()
}


func main() {
	//宣告一個結構體型別
	var root treeNode
	
	//初始化方式一
	root = treeNode{value:3}
	//初始化方式二
	root.left = &treeNode{}
	root.right = &treeNode{5,nil,nil}
	//初始化方式三
	root.right.left = new(treeNode)   
	//new(),只接受一個引數,這個引數是一個型別,分配好記憶體後,返回一個指向該型別記憶體地址的指標。同時請注意它同時把分配的記憶體置為零,也就是型別的零值。
	//這裡,root結構本身,而root.left是一個地址,在go中不論地址含是結構本身,一律用"."來訪問成員,  而C++中,訪問地址的成員要用"->"
	//初始化方法四 使用工廠方法
	root.right.right = creatNode(4) 
	
	nodes := []treeNode{
		{value:3},          //這裡相當於 treeNode{value:3}, 前面的treeNode省略掉了
		{},
		{6,nil,&root},
	}	
	fmt.Println(nodes)   //輸出結果: [{3 <nil> <nil>} {0 <nil> <nil>} {6 <nil> 0xc420090020}]
	 
	root.print()    //輸出結果: 3
	
	root.right.left.print()      //輸出結果:0
	root.right.left.setValue1(10)
	root.right.left.print()    //輸出結果:0  setValue1()為值傳遞,value沒有被改掉
	
	root.right.left.setValue2(20)
	root.right.left.print()     //輸出結果:20  setValue2()引用傳遞,value被改掉
	//這裡在呼叫的時候,會進行人性化處理,接受者是結構指標型別或者是實際的結構型別,呼叫者是結構指標或實際結構體,不管如何組合都是可以混用的
	(*root.right.left).print()     //輸出結果:20
	
	
	var pRoot *treeNode
	pRoot.setValue3(30)   //輸出結果:setting value to nil node!
	//這裡的pRoot 只有宣告 是一個nil指標,但它同樣可以呼叫setValue3()
	
	root.traverse()  //輸出:0 3 20 5 4
}

相關推薦

Go基礎面向物件結構方法

go語言的面向物件相對簡單,只支援封裝,不支援繼承和多型,go中用面向介面來做繼承和多型的任務 go中沒有class ,只有struct struct的建立 type treeNode struct {     value int     left, right *tr

PHP記錄面向物件Object-oriented programming,OOP瞭解下唄

在面向物件的程式設計(英語:Object-oriented programming,縮寫:OOP)中,物件是一個由資訊及對資訊進行處理的描述所組成的整體,是對現實世界的抽象,然而在現實世界裡我們所面對的事情都是物件,如計算機、電視機、自行車等,我們來看下物件的三個主要特徵:

Go語言學習第八課-結構Go語言的面向物件

      接下來講解一下Go語言中的面向物件思想程式設計。在Go語言面向物件與其它面嚮物件語言有著很大的差別。首先Go語言的不存在繼承和多型,而且不存在建構函式。並且Go語言不採用class來實現類,而是採用結構體加指標實現。不得不說,這讓類的定義變得很複雜,但是又不失合理

go語言-面向物件結構方法(十)

go語言僅支援封裝,不支援繼承和多型type node struct { value int left *node right *node } var root node root = node{value:1} //root := node{value:1} r

Go語言基礎十四—— Go語言切片,map,結構Json的序列化,反序列化

序列化和反序列化 序列化概念理解:就是將變數從記憶體中變成可儲存或傳輸的過程稱之為序列化,序列化之後,就可以把序列化後的內容寫入磁碟,或者通過網路傳輸到別的機器上。 反序列化則就是序列化反過來,把變數內容從序列化的物件重新讀到記憶體裡稱之為反序列化 序列化結構體案例: packa

JavaScript設計模式基礎面向物件的JavaScript

多型 多型的實際含義:同一操作作用與不同的物件上面,可以產生不同的解釋和不同的執行結果,就是說,給不同的物件傳送同一個訊息 的時候,這些物件會根據這個訊息分別給出不同的反饋 程式碼如下:      class Duck{}; class Chicken{}; let ma

JAVA基礎面向物件   概念

1、成員變數和區域性變數的區別: 1)在類中的位置不同:成員變數(類中,方法外),區域性變數(方法中或者方法宣告上_形式引數) 2)記憶體中的位置不同:成員變數(堆記憶體),區域性變數(棧記憶體) 3)生命週期不同:成員變數(隨著物件的建立而存在,隨著物件的消失

Go語言學習(十二)面向物件程式設計-結構

1.結構體的初始化方式 例如自定義一個結構體 package main import( "fmt" ) type Rect struct{ //type和struct為關鍵字 x,y float64 //結構體成員 widh

Go語言基礎面向物件程式設計中

1 Golang面向物件程式設計基本介紹 Golang仍然有面向物件程式設計的繼承,封裝和多型的特性,只是實現的方式和其它OPP語言不一樣,隨後分別介紹Golang對面向物件程式設計的三大特性是如何實現的。 2 面向物件程式設計-封裝 2.1 封裝介紹 封裝(encapsulation)就是把抽象出的欄位和對

週末班:Python基礎面向物件進階

面向物件進階 型別判斷 issubclass 首先,我們先看issubclass() 這個內建函式可以幫我們判斷x類是否是y型別的子類。 class Base: pass class Foo(Base): pass class Bar(Foo):

.NET基礎面向物件的實現和異常的處理基礎

轉自:http://www.cnblogs.com/edisonchou/p/4803879.html   面向物件的實現和異常的處理基礎  Index : (1)型別語法、記憶體管理和垃圾回收基礎 (2)面向物件的實現和異常的處理基礎 (3

go學習筆記-面向物件Methods, Interfaces

面向物件(Methods, Interfaces) Method method是附屬在一個給定的型別上的,他的語法和函式的宣告語法幾乎一樣,只是在func後面增加了一個receiver(也就是method所依從的主體)。 語法 func (r ReceiverType) funcName(param

javaSE面向物件程式設計->類物件——1 and 2

一、面向物件程式設計的簡介 在C語言的學習中我們所有的程式風格都是面向過程的,也就是比如兩個數相加這個程式段需要多次執行那麼我們在C語言中只能通過程式碼的賦值貼上才可以辦到,但是我們在面向過程程式設計裡面也有這樣類似的思想,就是函式。在java中我們採用面向物件的方法,就是可以將程式碼的可重

JavaSE面向物件

1.繼承(關鍵字extends) 繼承是兩個類之間的關係。當類Son繼承了一個已存在的類Father後,類Son就擁有了類Father所有的非private屬性和方法,同時還可以在Son類中新增新的屬性和方法。原來已存在的類稱為父類或基類,也可以稱為超類。新派生的類稱為原來的子類或是派生

JavaSE面向物件

1.static靜態修飾符 使用static修飾的成員變數、常量、方法和程式碼塊統稱為靜態成員。 靜態成員歸整個類所有,但不依賴於類的例項,只是別所有的例項所共享,只要這個類被JVM載入,就可以根據類名在全域性資料區域中找到他們,因此,靜態成員可以在任何例項物件建立之前訪問。 1.1st

黑馬程式設計師----Java基礎面向物件(最終)

------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g

黑馬程式設計師----Java基礎面向物件(封裝 繼承 多型)(二)

------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g

黑馬程式設計師----Java基礎面向物件(封裝 繼承 多型)

------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g

黑馬程式設計師----java基礎面向物件

------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g

Python面向物件1

知識框架: 1.面向過程vs面向物件 2.初識面向物件       類的相關知識       物件的相關知識       面向物件相關介紹 3.面向物件的三大特性