Golang入門教程(十四)結構體和類詳解


golang中並沒有明確的面向對象的說法,實在要扯上的話,可以將struct比作其它語言中的class。

類聲明

type Book struct {
    Title  string
    Author string
    intro  string
}

  這樣就聲明了一個類,其中沒有public、protected、private的的聲明。golang用另外一種做法來實現屬性的訪問權限:屬性的開頭字母是大寫的則在其它包中可以被訪問,否則只能在本包中訪問。類的聲明和方法亦是如此。

類方法聲明

// 類方法聲明-傳遞值對象
func (b Book) B1() {
	b.Title = "Book001"
	b.Author = "ErWan"
}

// 類方法聲明-傳遞指針對象
func (b *Book) B2() {
	b.Title = "Book002"
	b.Author = "Tinywan"
}

  和其它語言不一樣,golang聲明方法和普通方法一致,只是在func后增加了b Book這樣的聲明。加和沒有加*的區別在於一個是傳遞指針對象(加*),一個是傳遞值對象。

傳遞指針和對象的區別

package main

import "fmt"

// 類聲明
type Book struct {
	Title    string
	Author   string
	DateTime string
}

// 類方法聲明-傳遞值對象
func (b Book) B1() {
	b.Title = "Book001"
	b.Author = "ErWan"
}

// 類方法聲明-傳遞指針對象
func (b *Book) B2() {
	b.Title = "Book002"
	b.Author = "Tinywan"
}

func main() {
	/*聲明一個 Book 類型的變量 b ,並調用 B1() 和 B2()*/
	b := Book{"Def-Book", "Def-Author", "Def-DateTime"}

	fmt.Println("B1 調用前:", b.Title, b.Author, b.DateTime)
	b.B1()
	fmt.Println("B1 調用后:", b.Title)

	fmt.Println("------------------\r\n")
	fmt.Println("B2 調用前:", b.Title)
	b.B2()
	fmt.Println("B2 調用后:", b.Title)

}

 執行結果:

B1() 的接收者是值類型 Book, B2() 的接收者是值類型 *Book , 兩個方法內都是改變Name值。

小結:

  1、接收者可以看作是函數的第一個參數,即這樣的: func B1(b Book), func B2(b *Book)。 go不是面向對象的語言,所以用那種看起來像面向對象的語法來理解可能有偏差。

  2、當調用 b.B1() 時相當於 B1(b) ,實參和行參都是類型 Book,可以接受。此時在B1()中的b只是 "Def-Book" 的值拷貝,所以B1()的修改影響不到" Def-Book"。

  3、當調用 b.B2() => B2(b1),這是將 Book 類型傳給了 *Book 類型,go可能會取 b 的地址傳進去: B2(&b)。所以 B2() 的修改可以影響 b 。

 

 例如在一個beego 框架中我們要修改一個action的值,是這么定義的(為了修改內部結構的值。而不是傳遞一下)

func (this *InputController) InputGet(){
     // Get 方式接受 name := this.GetString("name") // 不使用模版,直接用 this.Ctx.WriteString 輸出字符串 this.Ctx.WriteString(name) }

值類型不可以改變值,而指針類型則是可以的

匿名結構體

p := struct {
    Name string
    Gender string
    Age uint8
}{"Robert", "Male", 33}

匿名結構體最大的用處是在內部臨時創建一個結構以封裝數據,而不必正式為其聲明相關規則。 

實例化對象

實例化對象有好幾種方式:

package main

// 類聲明
type Person struct {
	Name    string
	Age   	int
	Doc		[]string // slice切片
}

// 類方法聲明-傳遞值對象
func (p *Person) P1() {
	p.Name = "Tinywan"
	p.Age = 24
}

// 類方法聲明-傳遞指針對象
func (p *Person) P2() {
	p.Name = "Tinyaiai"
	p.Age = 22
}

func main() {

	// 實例化對象 實例化的時候可以初始化屬性值,如果沒有指明則默認為系統默認值
	p1 := &Person{}
	p1.Name = "ShaoBo Wan"
	p1.Age = 20

	p2 := &Person{Name:"HaHa"}

	p3 := new(Person)
	p3.Name = "New Name"

	p4 := Person{}
	p4.Name = "Name 001"
	p4.Age = 26

	p5 := Person{Name:"Name 002",Age:28}

	// 使用中如果包含數組(動態數組 slice切片),結構體的實例化需要加上類型如上如果intro的類型是[]string
	p6 := &Person{
        "zhangsan",
        25,
        []string{"lisi", "wangwu"},
    }
}

注意,最后一個實例化

    p6 := &Person{
        "zhangsan",
        25,
        []string{"lisi", "wangwu"},
    }

小結:

  1、使用中如果包含數組,結構體的實例化需要加上類型如上如果Doc的類型是[]string。  

  2、實例化的時候可以初始化屬性值,如果沒有指明則默認為系統默認值。

  3、加&符號和new的是指針對象,沒有的則是值對象,這點和php、java不一致,在傳遞對象的時候要根據實際情況來決定是要傳遞指針還是值

  4、當對象比較小的時候傳遞指針並不划算。

 繼承

確切的說golang中叫做組合(composition)

1、先初始化為空再賦值

// 先初始化為空再賦值
s1 := &Student{}
s1.schoole = "QiHua"

2、直接賦值

// 直接賦值
s2 := &Student{
	Persons: Persons{
		Name:"Tinywan",
		Age:24,
		Doc:[]string{"H1","h2"},
	},
	schoole:"BeiJin Schoole",
}

3、完整代碼

package main

import (
	"fmt"
)

// 類聲明
type Persons struct {
	Name    string
	Age   	int
	Doc		[]string // slice切片
}

// 獲取Name
func (p *Persons) getName() {
	fmt.Println("Name is ",p.Name)
}

type Student struct {
	// Student 屬性中聲明了 Persons,表示組合了Persons 的屬性和方法(屬性和方法都會被繼承)
	Persons
	Name string
	schoole string
}

func main() {

	// 先初始化為空再賦值
	s1 := &Student{}
	// 當訪問Name的時候默認為ProsePoem的 Name,如果需要訪問Persons 的 Name 屬性可以使用 s1.Persons.Name 來訪問方法同理。
	s1.Name = "Tinywan"
	s1.Persons.Name = "Persons Name"
	s1.schoole = "QiHua"
	fmt.Println("s1 = ",s1)
	fmt.Println("\r\n")

	// 直接賦值
	s2 := &Student{
		Persons: Persons{
			Name:"Tinywan",
			Age:24,
			Doc:[]string{"s2-Doc","s2-Doc"},
		},
		Name:"ErWan",
		schoole:"BeiJin-Schoole",
	}
	fmt.Println("s2 = ",s2)
}

方法的繼承和屬性一致

  

參考

1、https://segmentfault.com/a/1190000012325027

2、 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM