Golang結構體和指標
阿新 • • 發佈:2019-02-18
結構體定義
定義結構體和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()
}