go語言結構體入門

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

本文忽略了匿名結構體跟結構體匿名方法,一般作為開發人員不建議去玩這種技巧性但沒實際意義的東西,直接從結構體的值傳遞跟引用傳遞開始

2、值傳遞和引用傳遞

無論學習哪門語言,都基本會大談特談“值傳遞”和“引用傳遞”的問題,GO語言也免不了俗氣一把,在GO語言中除了切片(slice)、集合(map)、通道(channel)和介面(interface)之外,其它的都是值傳遞,看下面的例子:

/*聲明一個結構體*/

type employee struct {

name, address  string  // 姓名、住址

height, weight float64 // 身高、體重

}

 

/*定義方法,該方法入參為結構體,通過該方法修改結構體成員name的值*/

func modifyAttribute(emp employee) {

emp.name = "newer"

fmt.Println(emp)

}

 

/*測試方法*/

func main() {

// 初始化結構體並賦給emp

emp := employee{name: "eagle", address: "guangdong", height: 172.0, weight: 75.3}

// 修改之前列印結果

fmt.Println(emp)

// 調用方法修改name值並列印

modifyAttribute(emp)

// 修改之後列印結果

fmt.Println(emp)

}

執行並列印出結果

從結果上可以看出雖然在方法modifyAttribute中修改了name,但對於main方法中定義的emp並沒有造成影響,所以這是一個值傳遞。

C語言之所以經過這麼久的風風雨雨而經久不衰,其原因之一在於它對記憶體的操作,對記憶體的操作就意味著效能的提升,因為對結構體記憶體位址的操作效率遠高於結構體的複製(別緊張,這裡不講指標,呵呵)

接下來我們把入參由結構體修改為結構體指標

 

/*把入參由結構體修改為結構體指標*/

func modifyAttribute(emp *employee) {

emp.name = "newer"

fmt.Println(emp)

}

 

/*測試方法*/

func main() {

// 初始化結構體並賦給emp

emp := employee{name: "eagle", address: "guangdong", height: 172.0, weight: 75.3}

// 修改之前列印結果

fmt.Println(emp)

// 調用方法修改name值並列印

modifyAttribute(&emp)

// 修改之後列印結果

fmt.Println(emp)

}

執行並列印出結果

從結果上可以看出方法的修改影響到了main方法中emp的值,這不再是值傳遞,而是引用傳遞了 :)

 

3、再談嵌套結構體

由於結構體的嵌套在具體編碼中經常出現,上節寫的過於倉促,怕沒有解釋清楚,這裡再談一談關於結構體的嵌套問題

 

/*聲明figure結構體*/

type figure struct {

height, weight float64

}

 

/*聲明human結構體,裡面嵌套figure結構體*/

type human struct {

name, address string

figure

}

正如上章所說,結構體在使用之前先進行初始化,比較好理解的初始化方式是:字面值初始化

man := human{}  // 初始化human結構體,但不對成員賦值

// 採用字面值進行賦值

man.name = "eagle"

man.address = "guangdong"

man.height = 172   // 或者man.figure.height = 172

man.weight = 75.3  // 或者man.figure.weight = 75.3

這種賦值方式更物件導向化一些,從Java或者C++轉型過來的讀者可能更喜歡一些,但真正編碼過程中,我們會經常讀其他人寫的代碼,他們可能更習慣初始化和賦值一塊進行:

man := human{name:"eagle", address:"guangdong", figure:figure{height:172, weight:75.3}}

 

請各位稍休息一下,然後重點考慮下面的話:

在human結構體嵌套中,您會發現成員變數name有指定名稱和類型,同樣address也是,但有一個奇葩figure,它到底是成員名稱?還是結構體類型呢?

答案是:figure既是成員名稱又是類型,所以在初始化時才採用figure:figure{}的形式初始化。

若您理解了這句話,可以接著向下看了,否則需要重讀幾遍,再不清楚的話可以留言給我 :)

 

4、物件導向

在《【4】GO語言類型和為類型增加方法》中講到為類型增加方法,大家融會貫通一下:

 

// 為int類型起一個別名Integer

type Integer int

 

// 為類型Integer增加一個新方法LessThan

func (a Integer) LessThan (b Integer) bool{

        return a < b

}

 

// 然後就可以物件導向編程了

var a Integer = 5 // 定義一個對象a ,其類型為Integer

a.LessThan(8)      // 調用對象a的方法LessThan()

再看一下結構體的聲明

 

// 為struct類型起一個別名employee

type employee struct{

        name, address string

}

 

// 用方法類比一個構造器

func newEmployee(name, address string) employee{

        return employee{name, address}

}

 

// 定義一個修改employee住址的方法

func ModifyAddress(emp *employee){

        emp.address = "shenzhen"

}

 

// 為類型employee增加一個比較方法:只要名稱和地址相同,則認為兩個對象相同

func (src employee) IsEqual(dest employee) bool{

       return src.name == dest.name && src.address == dest.address

}

 

// 採用物件導向編程的方式使用結構體

// 初始化對象src和dest,且兩者賦予相同的值

var src = newEmployee("eagle", "guangdong")

var dest = newEmployee("eagle", "guangdong")

fmt.Println(src.IsEqual(dest))  // 列印結果為true

 

// 修改目標的住址

ModifyAddress(&dest)

fmt.Println(src.IsEqual(dest))  // 列印結果為false

 

好了,到此結構體基本上已介紹完,但還有一些更細節的東西沒有介紹,例如:

  • 採用new的方式初始化結構體

  • 結構體是一種複合類型,所以它可以和指標結合,本文都沒有深入涉及

等等

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.