Go 學習筆記(33)— Go 自定義類型 type(自定義結構體、結構體初始化、自定義接口)

1. 自定義類型格式

用戶自定義類型使用關鍵字 type ,其語法格式是:

type newType oldType

oldType 可以是自定義類型、預聲明類型、未命名類型中的任意一種。

newType 是新類型的標識符,與 oldType 具有相同的底層類型,並且都繼承了底層類型的操作集合(這裏的操作不是方法,比如底層類型是 map ,支持 range 迭代訪問,則新類型也可以使用 range 迭代訪問) 。除此之外, newTypeoldType 是兩個完全不同的類型, newType 不會繼承 oldType 的方法。

無論 oldType 是什麼類型,使用 type 聲明的新類型都是一種命名類型,也就是說,自定義類型都是命名類型。

type INT int //INT 是一個使用預聲明類型聲明的自定義類型
type Map map[string]string //Map 是一個使用類型字面量聲明的自定義類型
type myMap Map //myMap 是一個自定義類型Map 聲明的自定義類型
// INT, Map 、myMap 都是命名類型

2. 自定義 struct 類型

struct 類型是 Go 語言自定義類型的普遍的形式,是 Go 語言類型擴展的基石,也是 Go 語言面向對象承載的基礎。

前面章節將 struct 劃爲未命名類型,那時的 struct 是使用字面量來表示的,如果使用 type 語句聲明,則這個新類型就是命名類型。例如:

// 使用 type 自定義的結構類型屬於命名類型
type XXXName struct {
    field1 type1
    field2 type2
}

// errorString 是一個自定義結構類型,也是命名類型
type errorString struct {
    s string
}

// 結構字面量屬於未命名類型
struct {
    field1 type1
    field2 type2
}

// struct{} 是非命名類型空結構
var s = struct{}{}

2.1 struct 初始化

Person 結構爲例來講一下結構的初始化的方法。例如:

type Person struct {
    name string
    age int
}
  1. 按照字段順序進行初始化
// 以下三種寫法都可以
a := Person{"Tom", 25}

b := Person{
    	"Tom",
          25}

c := Person{
    "Tom",
      25,	// 必須加逗號
      }

不推薦這種寫法,一旦結構體增加字段,則需要重新修改初始化語句的順序。

  1. 指定字段名進行初始化

推薦這種寫法,結構體增加字段後,無需修改原有初始化語句的順序。

a := Person{name:"Tom", age:25}

b := Person{
    name:"Tom", 
    age:25}

b := Person{
    name:"Tom", 
    age:25, // 加逗號
}	// 初始化語句結尾的 } 獨佔一行,則最後一個字段的後面一定要帶上逗號。
  1. 使用 new 創建內置函數,字段默認初始化爲其類型的零值, 返回值是指向結構的指針。例如:
p := new(Person)
// 此時 name 爲 "", age 爲 0

這種方法不常用,一般使用 struct 都不會將所有字段初始化爲零值。

  1. 一次初始化一個字段
p := Person{}
p.name = "Tom"
p.age = 25

這種方法不常用,這是一種結構化的編程思維,沒有封裝,違背了 struct 本身抽象封裝的理念。

  1. 使用構造函數進行初始化

這是推薦的一種方法,當結構發生變化時,構造函數可以屏蔽細節。下面是標準庫中 errorsNew 函數示例。

//${GOROOT)/src/errors/errors.go
//New returns an error that formats as the given text.
func New(text string) error {
	return &errorString{text}
}

//errorStr 工ng is a trivial implementation of error .
type errorString struct {
	s string
}

2.2 結構字段的特點

結構的字段可以是任意的類型,基本類型、接口類型、指針類型、函數類型都可以作爲 struct 的字段。結構字段的類型名必須唯一, struct 字段類型可以是普通類型,也可以是指針。另外,結構支持內嵌自身的指針,這也是實現樹形和鏈表等複雜數據結構的基礎。例如:

// 標準庫container/list
type Element struct {
// 指向自身類型的指針
    next, prev *Element
    list *List
    Value interface{}
}

2.3 匿名字段

在定義 struct 的過程中,如果字段只給出字段類型,沒有給出宇段名, 則稱這樣的字段爲“匿名字段”。被匿名嵌入的字段必須是命名類型或命名類型的指針,類型字面量不能作爲匿名字段使用。

匿名字段的字段名默認就是類型名,如果匿名字段是指針類型,則默認的字段名就是指針指向的類型名。但一個結構體裏面不能同時存在某一類型及其指針類型的匿名字段, 原因是二者的字段名相等。如果嵌入的字段來自其他包,則需要加上包名,並且必須是其他包可以導出的類型。示例如下:

3. 自定義接口類型

接口字面量是非命名類型,但自定義接口類型是命名類型。自定義接口類型同樣使用 type 關鍵字聲明。示例如下:

// interface{} 是接口字面量類型標識, 所以 i 是非命名類型交量
var i interface{}
// Reader 是自定義接口類型,屬於命名類型
type Reader interface {
    Read (p []byte) (n int , err error )
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章