go 結構體 (struct) 和方法 (method)

旱鴨子發表於2018-11-07

結構體(struct)

go中沒有物件這一概念,所以採用了結構體的概念,結構體在go中有著非常重要的位置。結構體是值型別,所以可以使用new函式來建立。結構體中欄位必須唯一。

結構體定義如下:

type identifier struct {
    filed type
    filed type
}
複製程式碼

filed就是結構體的欄位名字,type是欄位的型別,如果暫時不知道命名,可以使用 _ 來進行佔位。欄位可以使用任何型別,甚至是結構體本身,也可以是函式或者介面。 一般來說,給結構體的欄位賦值這樣即可:

var s T
s.a = 1
s.b = 2
複製程式碼

使用new函式給一個新的結構體變數分配記憶體,返回已分配記憶體:

var t *T = new(T)
// or
t := new(T)
複製程式碼

例子:


type Person struct {
    Name string
    Age  int
    Sex  int
}

func main() {
    person := new(Person)
    person.Name = "Tim"
    person.Age  = 10
    person.Sex  = 1
    
    //or
    
    person := &Person{"Tim", 10 , 1}
    
    fmt.Println(person)
}

// 輸出 &{Tim, 10, 1}

複製程式碼

就像面嚮物件語言那樣,可以使用點來給欄位進行賦值,同樣的也可以通過點來進行獲取欄位的值。

結構體同樣可以作為引數進行傳遞:

func getPersonName(p *Person) string {
    return p.Name
}

func main() {
    ...
    
    fmt.Prinltn(getPersonName(person))
}
// 輸出 Tim
複製程式碼

如果想知道一個結構體佔用了多少記憶體,可以使用:

size := unsafe.Sizeof(T{}}
複製程式碼

結構體中除了欄位和型別外,還有一個可選的標籤,一個欄位的輔助字串,只有reflect能獲取它。

例子:

type Person struct {
    Name string "Name"
    Age  int    "Age"
    Sex  int    "Sex"
}

func main() {
    person := Person{}
    person.Name = "Tim"
    person.Age  = 10
    person.Sex  = 1
    
    for i := 0; i < 3; i++ {
        refTag(person, i)
    }
}

func refTag(p Person, i int) {
    pType := reflect.TypeOf(p)
    iFiled := pType.Filed(i)
    fmt.Println(iFiled.Tag)
}

//out  
複製程式碼

reflect.TypeOf可以獲取變數的正確型別,如果變數是一個結構體,就可以通過Filed來索引該結構體的欄位,然後就可以使用Tag屬性。

go結構體還支援一個特殊欄位,匿名欄位。這些欄位沒有顯式的名字,只有欄位型別,此時欄位型別也就是欄位的名字,匿名欄位也可以是一種結構體。

例子:

type Test1 struct {
    t1 int
    t2 int
}

type Test struct {
    a int
    b string
    bool
    Test1
}

func main() {
    test := new(Test)
    test.a = 1
    test.b = "2"
    test.bool = true
    test.t1 = 2
    test.t2 = 3
    
    fmt.Println(test)
}

//out &{1, "2", true, 2, 3}
複製程式碼

通過test.bool的名字來獲取匿名欄位的資料,於是可以得出一個結論,在一個結構體中對於每一種資料型別只能有一個匿名欄位。 在結構體內嵌結構體是,如果遇到命名衝突但是又都需要保留時,可以使用:

Test.Test1.Filed
複製程式碼

這樣使用就避免了命名衝突。

方法

go方法是作用在接收者上的一個函式,接收者是某種型別的變數,因此方法是一種型別的函式。接收者型別幾乎可以任何型別,指標型別和函式型別就不行。 因為方法是函式,所以方法不能被過載,對於一個型別只有一個既定名稱的方法。 定義方法的格式如下:

func (r receiver_type) methodName(parmeter_list) (value_list){
    ...
}
複製程式碼

r是receiver_type的例項,methodName是r的方法名,呼叫也很簡單,r.methodName() 即可。 例子:

type Person struct {
    Name string
    Age  int
}

func (p *Person) GetName() string {
    return p.Name
}

func (p *Person) GetAge() int {
    return p.Age
}

func main() {
    p := new(Person)
    p.Name = "1"
    p.Age  = 2
    
    fmt.Prinltn(p.GetName())
    fmt.Prinltn(p.GetAge())
}

// out   "1"    2
複製程式碼

go 結構體 (struct) 和方法 (method)

微信搜尋「goentry-xyz」,關注公眾號「燈下獨碼」

相關文章