1. 程式人生 > >Golang結構體和指標

Golang結構體和指標

結構體定義

定義結構體和C語言一樣,使用struct關鍵字。在結構體內部定義它們的成員變數和型別,只是型別要放到後面,並且變數之間不用逗號。如果成員變數的型別相同的話,可以把它們寫到同一行。

type Student struct {
    name   string
    age    int
    weight float32
    score  []int
}

結構體初始化

可以變數初始化和指標初始化,程式碼如下:

package main

import (
    "fmt"
)

type Student struct {
    name   string
age int weight float32 score []int } func main() { stu01 := Student{"qixuxiang", 23, 55.5, []int{95, 96, 98}} //按照欄位順序進行初始化 stu02 := Student{age: 23, weight: 55.5, score: []int{97, 98}, name: "sb"} //通過 field:value 形式初始化,該方式可以自定義初始化欄位的順序 var ptu1 = &Student{"qishuangzhu"
, 23, 55.0, []int{2, 3, 6, 4, 5, 9}} //初始化得到物件指標 pp := new(Student) //使用 new 關鍵字建立一個指標 *pp = Student{"qishuangming", 23, 65.0, []int{2, 3, 6}} fmt.Printf("stu01.age is %d\n", stu01.age) fmt.Printf("stu02 have %d subjects\n", len(stu02.score)) fmt.Printf("stu03's weight is %f\n"
, (*ptu1).weight) fmt.Printf("stu03's weight is %f\n", ptu1.weight) //Go語言自帶隱式解引用 fmt.Printf("stu pp have %d subjects\n", len((*pp).score)) fmt.Printf("stu pp have %d subjects\n", len(pp.score)) //Go語言自帶隱式解引用 fmt.Printf("stu01 info is %#v\n", stu01) //結構體可以直接列印 }

Go語言指標

在Go語言中,直接砍掉了C語言指標最複雜的指標運算部分,只留下了獲取指標(&運算子)和獲取物件(*運算子)的運算,使用方法和C語言很類似。但不同的是,Go語言中沒有 -> 操作符來呼叫指標所屬的成員,而與一般物件一樣,都是使用 . 來呼叫

Go語言自帶指標隱式解引用 :對於一些複雜型別的指標, 如果要訪問成員變數時候需要寫成類似 *p.field的形式時,只需要p.field即可訪問相應的成員。

示例程式碼見上面程式碼的後四行。

值型別和指標型別區別

對於一個函式(或方法),如果函式的引數(或接收者)是物件指標時,表示此物件是可被修改的;相反的,如果是物件時,表示是不可修改的(但如果該物件本身就是引用型別,如 map\func\chan 等,則本質上是可以修改的)。所以一般的做法是,方法的接收者習慣性使用物件指標,而不是物件,一方面可以在想修改物件時進行修改,另一方面也減少引數傳遞的拷貝成本。

   另外,有一點尤為特殊,如果是作為函式的引數,則函式定義時,是使用物件還是物件指標,是有本質區別的,在使用物件作為引數的函式中,不能傳入物件指標,同樣的,在使用物件指標作為引數的函式中,也不能傳入物件,否則編譯器會報錯。但如果是方法,則接收者定義為物件還是物件指標,都可以接收物件和物件指標的呼叫。下面我們來定義相關的函式和方法如下:

package main


import "fmt"

type Player struct{
    userid int
    username string
}


//傳入 Player 物件引數
func print_obj(player Player) {
    //player.username = "new"  //修改並不會影響傳入的物件本身
    fmt.Println("userid:", player.userid)
}

//傳入 Player 物件指標引數
func print_ptr(player *Player){
    player.username = "new01"
    fmt.Printf("userid is %d\n",player.userid)
    fmt.Printf("username is %s\n",player.username)
}

//接收者為 Player 物件的方法,方法接收者的變數,按照 GO 語言的習慣一般不用 this/self ,而是使用接收者型別的第一個小寫字母,可以看標準庫中的程式碼風格。
func (p Player) m_print_obj(){
    //p.username = "new02"  ////修改並不會影響傳入的物件本身
    fmt.Printf("userid  is %d\n",p.userid)

}

//接收者為 Player 物件指標的方法
func (p *Player) m_print_ptr(){
    p.username = "new03"
    fmt.Printf("userid  is  %d\n",p.userid)
    fmt.Printf("username is %s\n",p.username)
}



func main(){
    player01 := Player{12 ,"test"}
    pp := &Player {15 ,"newname"}
    print_obj(player01)
    print_ptr(pp)
    player01.m_print_obj()
    pp.m_print_ptr()
}